GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/rcamera.h
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 110 0.0%
Branches: 0 82 0.0%

Line Branch Exec Source
1 /*******************************************************************************************
2 *
3 * rcamera - Basic camera system with support for multiple camera modes
4 *
5 * CONFIGURATION:
6 * #define RCAMERA_IMPLEMENTATION
7 * Generates the implementation of the library into the included file.
8 * If not defined, the library is in header only mode and can be included in other headers
9 * or source files without problems. But only ONE file should hold the implementation.
10 *
11 * #define RCAMERA_STANDALONE
12 * If defined, the library can be used as standalone as a camera system but some
13 * functions must be redefined to manage inputs accordingly.
14 *
15 * CONTRIBUTORS:
16 * Ramon Santamaria: Supervision, review, update and maintenance
17 * Christoph Wagner: Complete redesign, using raymath (2022)
18 * Marc Palau: Initial implementation (2014)
19 *
20 *
21 * LICENSE: zlib/libpng
22 *
23 * Copyright (c) 2022-2023 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5)
24 *
25 * This software is provided "as-is", without any express or implied warranty. In no event
26 * will the authors be held liable for any damages arising from the use of this software.
27 *
28 * Permission is granted to anyone to use this software for any purpose, including commercial
29 * applications, and to alter it and redistribute it freely, subject to the following restrictions:
30 *
31 * 1. The origin of this software must not be misrepresented; you must not claim that you
32 * wrote the original software. If you use this software in a product, an acknowledgment
33 * in the product documentation would be appreciated but is not required.
34 *
35 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
36 * as being the original software.
37 *
38 * 3. This notice may not be removed or altered from any source distribution.
39 *
40 **********************************************************************************************/
41
42 #ifndef RCAMERA_H
43 #define RCAMERA_H
44
45 //----------------------------------------------------------------------------------
46 // Defines and Macros
47 //----------------------------------------------------------------------------------
48 // Function specifiers definition
49 #ifndef RLAPI
50 #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
51 #endif
52
53 #if defined(RCAMERA_STANDALONE)
54 #define CAMERA_CULL_DISTANCE_NEAR 0.01
55 #define CAMERA_CULL_DISTANCE_FAR 1000.0
56 #else
57 #define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR
58 #define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR
59 #endif
60
61 //----------------------------------------------------------------------------------
62 // Types and Structures Definition
63 // NOTE: Below types are required for standalone usage
64 //----------------------------------------------------------------------------------
65 #if defined(RCAMERA_STANDALONE)
66 // Vector2, 2 components
67 typedef struct Vector2 {
68 float x; // Vector x component
69 float y; // Vector y component
70 } Vector2;
71
72 // Vector3, 3 components
73 typedef struct Vector3 {
74 float x; // Vector x component
75 float y; // Vector y component
76 float z; // Vector z component
77 } Vector3;
78
79 // Matrix, 4x4 components, column major, OpenGL style, right-handed
80 typedef struct Matrix {
81 float m0, m4, m8, m12; // Matrix first row (4 components)
82 float m1, m5, m9, m13; // Matrix second row (4 components)
83 float m2, m6, m10, m14; // Matrix third row (4 components)
84 float m3, m7, m11, m15; // Matrix fourth row (4 components)
85 } Matrix;
86
87 // Camera type, defines a camera position/orientation in 3d space
88 typedef struct Camera3D {
89 Vector3 position; // Camera position
90 Vector3 target; // Camera target it looks-at
91 Vector3 up; // Camera up vector (rotation over its axis)
92 float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
93 int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
94 } Camera3D;
95
96 typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
97
98 // Camera projection
99 typedef enum {
100 CAMERA_PERSPECTIVE = 0, // Perspective projection
101 CAMERA_ORTHOGRAPHIC // Orthographic projection
102 } CameraProjection;
103
104 // Camera system modes
105 typedef enum {
106 CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
107 CAMERA_FREE, // Camera free mode
108 CAMERA_ORBITAL, // Camera orbital, around target, zoom supported
109 CAMERA_FIRST_PERSON, // Camera first person
110 CAMERA_THIRD_PERSON // Camera third person
111 } CameraMode;
112 #endif
113
114 //----------------------------------------------------------------------------------
115 // Global Variables Definition
116 //----------------------------------------------------------------------------------
117 //...
118
119 //----------------------------------------------------------------------------------
120 // Module Functions Declaration
121 //----------------------------------------------------------------------------------
122
123 #if defined(__cplusplus)
124 extern "C" { // Prevents name mangling of functions
125 #endif
126
127 RLAPI Vector3 GetCameraForward(Camera *camera);
128 RLAPI Vector3 GetCameraUp(Camera *camera);
129 RLAPI Vector3 GetCameraRight(Camera *camera);
130
131 // Camera movement
132 RLAPI void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane);
133 RLAPI void CameraMoveUp(Camera *camera, float distance);
134 RLAPI void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane);
135 RLAPI void CameraMoveToTarget(Camera *camera, float delta);
136
137 // Camera rotation
138 RLAPI void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget);
139 RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp);
140 RLAPI void CameraRoll(Camera *camera, float angle);
141
142 RLAPI Matrix GetCameraViewMatrix(Camera *camera);
143 RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
144
145 #if defined(__cplusplus)
146 }
147 #endif
148
149 #endif // RCAMERA_H
150
151
152 /***********************************************************************************
153 *
154 * CAMERA IMPLEMENTATION
155 *
156 ************************************************************************************/
157
158 #if defined(RCAMERA_IMPLEMENTATION)
159
160 #include "raymath.h" // Required for vector maths:
161 // Vector3Add()
162 // Vector3Subtract()
163 // Vector3Scale()
164 // Vector3Normalize()
165 // Vector3Distance()
166 // Vector3CrossProduct()
167 // Vector3RotateByAxisAngle()
168 // Vector3Angle()
169 // Vector3Negate()
170 // MatrixLookAt()
171 // MatrixPerspective()
172 // MatrixOrtho()
173 // MatrixIdentity()
174
175 // raylib required functionality:
176 // GetMouseDelta()
177 // GetMouseWheelMove()
178 // IsKeyDown()
179 // IsKeyPressed()
180 // GetFrameTime()
181
182 //----------------------------------------------------------------------------------
183 // Defines and Macros
184 //----------------------------------------------------------------------------------
185 #define CAMERA_MOVE_SPEED 0.09f
186 #define CAMERA_ROTATION_SPEED 0.03f
187 #define CAMERA_PAN_SPEED 0.2f
188
189 // Camera mouse movement sensitivity
190 #define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
191 #define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
192
193 #define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
194
195
196 #define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 8.0f
197 #define CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f
198 #define CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f
199
200 // PLAYER (used by camera)
201 #define PLAYER_MOVEMENT_SENSITIVITY 20.0f
202
203 //----------------------------------------------------------------------------------
204 // Types and Structures Definition
205 //----------------------------------------------------------------------------------
206 //...
207
208 //----------------------------------------------------------------------------------
209 // Global Variables Definition
210 //----------------------------------------------------------------------------------
211 //...
212
213 //----------------------------------------------------------------------------------
214 // Module specific Functions Declaration
215 //----------------------------------------------------------------------------------
216 //...
217
218 //----------------------------------------------------------------------------------
219 // Module Functions Definition
220 //----------------------------------------------------------------------------------
221 // Returns the cameras forward vector (normalized)
222 Vector3 GetCameraForward(Camera *camera)
223 {
224 return Vector3Normalize(Vector3Subtract(camera->target, camera->position));
225 }
226
227 // Returns the cameras up vector (normalized)
228 // Note: The up vector might not be perpendicular to the forward vector
229 Vector3 GetCameraUp(Camera *camera)
230 {
231 return Vector3Normalize(camera->up);
232 }
233
234 // Returns the cameras right vector (normalized)
235 Vector3 GetCameraRight(Camera *camera)
236 {
237 Vector3 forward = GetCameraForward(camera);
238 Vector3 up = GetCameraUp(camera);
239
240 return Vector3CrossProduct(forward, up);
241 }
242
243 // Moves the camera in its forward direction
244 void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane)
245 {
246 Vector3 forward = GetCameraForward(camera);
247
248 if (moveInWorldPlane)
249 {
250 // Project vector onto world plane
251 forward.y = 0;
252 forward = Vector3Normalize(forward);
253 }
254
255 // Scale by distance
256 forward = Vector3Scale(forward, distance);
257
258 // Move position and target
259 camera->position = Vector3Add(camera->position, forward);
260 camera->target = Vector3Add(camera->target, forward);
261 }
262
263 // Moves the camera in its up direction
264 void CameraMoveUp(Camera *camera, float distance)
265 {
266 Vector3 up = GetCameraUp(camera);
267
268 // Scale by distance
269 up = Vector3Scale(up, distance);
270
271 // Move position and target
272 camera->position = Vector3Add(camera->position, up);
273 camera->target = Vector3Add(camera->target, up);
274 }
275
276 // Moves the camera target in its current right direction
277 void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane)
278 {
279 Vector3 right = GetCameraRight(camera);
280
281 if (moveInWorldPlane)
282 {
283 // Project vector onto world plane
284 right.y = 0;
285 right = Vector3Normalize(right);
286 }
287
288 // Scale by distance
289 right = Vector3Scale(right, distance);
290
291 // Move position and target
292 camera->position = Vector3Add(camera->position, right);
293 camera->target = Vector3Add(camera->target, right);
294 }
295
296 // Moves the camera position closer/farther to/from the camera target
297 void CameraMoveToTarget(Camera *camera, float delta)
298 {
299 float distance = Vector3Distance(camera->position, camera->target);
300
301 // Apply delta
302 distance += delta;
303
304 // Distance must be greater than 0
305 if (distance <= 0) distance = 0.001f;
306
307 // Set new distance by moving the position along the forward vector
308 Vector3 forward = GetCameraForward(camera);
309 camera->position = Vector3Add(camera->target, Vector3Scale(forward, -distance));
310 }
311
312 // Rotates the camera around its up vector
313 // Yaw is "looking left and right"
314 // If rotateAroundTarget is false, the camera rotates around its position
315 // Note: angle must be provided in radians
316 void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget)
317 {
318 // Rotation axis
319 Vector3 up = GetCameraUp(camera);
320
321 // View vector
322 Vector3 targetPosition = Vector3Subtract(camera->target, camera->position);
323
324 // Rotate view vector around up axis
325 targetPosition = Vector3RotateByAxisAngle(targetPosition, up, angle);
326
327 if (rotateAroundTarget)
328 {
329 // Move position relative to target
330 camera->position = Vector3Subtract(camera->target, targetPosition);
331 }
332 else // rotate around camera.position
333 {
334 // Move target relative to position
335 camera->target = Vector3Add(camera->position, targetPosition);
336 }
337 }
338
339 // Rotates the camera around its right vector, pitch is "looking up and down"
340 // - lockView prevents camera overrotation (aka "somersaults")
341 // - rotateAroundTarget defines if rotation is around target or around its position
342 // - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE)
343 // NOTE: angle must be provided in radians
344 void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp)
345 {
346 // Up direction
347 Vector3 up = GetCameraUp(camera);
348
349 // View vector
350 Vector3 targetPosition = Vector3Subtract(camera->target, camera->position);
351
352 if (lockView)
353 {
354 // In these camera modes we clamp the Pitch angle
355 // to allow only viewing straight up or down.
356
357 // Clamp view up
358 float maxAngleUp = Vector3Angle(up, targetPosition);
359 maxAngleUp -= 0.001f; // avoid numerical errors
360 if (angle > maxAngleUp) angle = maxAngleUp;
361
362 // Clamp view down
363 float maxAngleDown = Vector3Angle(Vector3Negate(up), targetPosition);
364 maxAngleDown *= -1.0f; // downwards angle is negative
365 maxAngleDown += 0.001f; // avoid numerical errors
366 if (angle < maxAngleDown) angle = maxAngleDown;
367 }
368
369 // Rotation axis
370 Vector3 right = GetCameraRight(camera);
371
372 // Rotate view vector around right axis
373 targetPosition = Vector3RotateByAxisAngle(targetPosition, right, angle);
374
375 if (rotateAroundTarget)
376 {
377 // Move position relative to target
378 camera->position = Vector3Subtract(camera->target, targetPosition);
379 }
380 else // rotate around camera.position
381 {
382 // Move target relative to position
383 camera->target = Vector3Add(camera->position, targetPosition);
384 }
385
386 if (rotateUp)
387 {
388 // Rotate up direction around right axis
389 camera->up = Vector3RotateByAxisAngle(camera->up, right, angle);
390 }
391 }
392
393 // Rotates the camera around its forward vector
394 // Roll is "turning your head sideways to the left or right"
395 // Note: angle must be provided in radians
396 void CameraRoll(Camera *camera, float angle)
397 {
398 // Rotation axis
399 Vector3 forward = GetCameraForward(camera);
400
401 // Rotate up direction around forward axis
402 camera->up = Vector3RotateByAxisAngle(camera->up, forward, angle);
403 }
404
405 // Returns the camera view matrix
406 Matrix GetCameraViewMatrix(Camera *camera)
407 {
408 return MatrixLookAt(camera->position, camera->target, camera->up);
409 }
410
411 // Returns the camera projection matrix
412 Matrix GetCameraProjectionMatrix(Camera *camera, float aspect)
413 {
414 if (camera->projection == CAMERA_PERSPECTIVE)
415 {
416 return MatrixPerspective(camera->fovy*DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR);
417 }
418 else if (camera->projection == CAMERA_ORTHOGRAPHIC)
419 {
420 double top = camera->fovy/2.0;
421 double right = top*aspect;
422
423 return MatrixOrtho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR);
424 }
425
426 return MatrixIdentity();
427 }
428
429 #if !defined(RCAMERA_STANDALONE)
430 // Update camera position for selected mode
431 // Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
432 void UpdateCamera(Camera *camera, int mode)
433 {
434 Vector2 mousePositionDelta = GetMouseDelta();
435
436 bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
437 bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
438 bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
439 bool rotateUp = false;
440
441 if (mode == CAMERA_ORBITAL)
442 {
443 // Orbital can just orbit
444 Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime());
445 Vector3 view = Vector3Subtract(camera->position, camera->target);
446 view = Vector3Transform(view, rotation);
447 camera->position = Vector3Add(camera->target, view);
448 }
449 else
450 {
451 // Camera rotation
452 if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
453 if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
454 if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget);
455 if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget);
456 if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED);
457 if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);
458
459 // Camera movement
460 if (!IsGamepadAvailable(0))
461 {
462 // Camera pan (for CAMERA_FREE)
463 if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
464 {
465 const Vector2 mouseDelta = GetMouseDelta();
466 if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
467 if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
468 if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
469 if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
470 }
471 else
472 {
473 // Mouse support
474 CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
475 CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
476 }
477
478 // Keyboard support
479 if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
480 if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
481 if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
482 if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
483 }
484 else
485 {
486 // Gamepad controller support
487 CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
488 CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
489
490 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
491 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
492 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
493 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
494 }
495
496 if (mode == CAMERA_FREE)
497 {
498 if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
499 if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
500 }
501 }
502
503 if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE))
504 {
505 // Zoom target distance
506 CameraMoveToTarget(camera, -GetMouseWheelMove());
507 if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f);
508 if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
509 }
510 }
511 #endif // !RCAMERA_STANDALONE
512
513 // Update camera movement, movement/rotation values should be provided by user
514 void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
515 {
516 // Required values
517 // movement.x - Move forward/backward
518 // movement.y - Move right/left
519 // movement.z - Move up/down
520 // rotation.x - yaw
521 // rotation.y - pitch
522 // rotation.z - roll
523 // zoom - Move towards target
524
525 bool lockView = true;
526 bool rotateAroundTarget = false;
527 bool rotateUp = false;
528 bool moveInWorldPlane = true;
529
530 // Camera rotation
531 CameraPitch(camera, -rotation.y*DEG2RAD, lockView, rotateAroundTarget, rotateUp);
532 CameraYaw(camera, -rotation.x*DEG2RAD, rotateAroundTarget);
533 CameraRoll(camera, rotation.z*DEG2RAD);
534
535 // Camera movement
536 CameraMoveForward(camera, movement.x, moveInWorldPlane);
537 CameraMoveRight(camera, movement.y, moveInWorldPlane);
538 CameraMoveUp(camera, movement.z);
539
540 // Zoom target distance
541 CameraMoveToTarget(camera, zoom);
542 }
543
544 #endif // RCAMERA_IMPLEMENTATION
545