aboutsummaryrefslogtreecommitdiff
path: root/raylib/src/rcamera.h
diff options
context:
space:
mode:
Diffstat (limited to 'raylib/src/rcamera.h')
-rw-r--r--raylib/src/rcamera.h555
1 files changed, 555 insertions, 0 deletions
diff --git a/raylib/src/rcamera.h b/raylib/src/rcamera.h
new file mode 100644
index 0000000..bd2b36e
--- /dev/null
+++ b/raylib/src/rcamera.h
@@ -0,0 +1,555 @@
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-2024 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
50// Function specifiers in case library is build/used as a shared library (Windows)
51// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
52#if defined(_WIN32)
53#if defined(BUILD_LIBTYPE_SHARED)
54#if defined(__TINYC__)
55#define __declspec(x) __attribute__((x))
56#endif
57#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
58#elif defined(USE_LIBTYPE_SHARED)
59#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
60#endif
61#endif
62
63#ifndef RLAPI
64 #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
65#endif
66
67#if defined(RCAMERA_STANDALONE)
68 #define CAMERA_CULL_DISTANCE_NEAR 0.01
69 #define CAMERA_CULL_DISTANCE_FAR 1000.0
70#else
71 #define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR
72 #define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR
73#endif
74
75//----------------------------------------------------------------------------------
76// Types and Structures Definition
77// NOTE: Below types are required for standalone usage
78//----------------------------------------------------------------------------------
79#if defined(RCAMERA_STANDALONE)
80 // Vector2, 2 components
81 typedef struct Vector2 {
82 float x; // Vector x component
83 float y; // Vector y component
84 } Vector2;
85
86 // Vector3, 3 components
87 typedef struct Vector3 {
88 float x; // Vector x component
89 float y; // Vector y component
90 float z; // Vector z component
91 } Vector3;
92
93 // Matrix, 4x4 components, column major, OpenGL style, right-handed
94 typedef struct Matrix {
95 float m0, m4, m8, m12; // Matrix first row (4 components)
96 float m1, m5, m9, m13; // Matrix second row (4 components)
97 float m2, m6, m10, m14; // Matrix third row (4 components)
98 float m3, m7, m11, m15; // Matrix fourth row (4 components)
99 } Matrix;
100
101 // Camera type, defines a camera position/orientation in 3d space
102 typedef struct Camera3D {
103 Vector3 position; // Camera position
104 Vector3 target; // Camera target it looks-at
105 Vector3 up; // Camera up vector (rotation over its axis)
106 float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
107 int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
108 } Camera3D;
109
110 typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
111
112 // Camera projection
113 typedef enum {
114 CAMERA_PERSPECTIVE = 0, // Perspective projection
115 CAMERA_ORTHOGRAPHIC // Orthographic projection
116 } CameraProjection;
117
118 // Camera system modes
119 typedef enum {
120 CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
121 CAMERA_FREE, // Camera free mode
122 CAMERA_ORBITAL, // Camera orbital, around target, zoom supported
123 CAMERA_FIRST_PERSON, // Camera first person
124 CAMERA_THIRD_PERSON // Camera third person
125 } CameraMode;
126#endif
127
128//----------------------------------------------------------------------------------
129// Global Variables Definition
130//----------------------------------------------------------------------------------
131//...
132
133//----------------------------------------------------------------------------------
134// Module Functions Declaration
135//----------------------------------------------------------------------------------
136
137#if defined(__cplusplus)
138extern "C" { // Prevents name mangling of functions
139#endif
140
141RLAPI Vector3 GetCameraForward(Camera *camera);
142RLAPI Vector3 GetCameraUp(Camera *camera);
143RLAPI Vector3 GetCameraRight(Camera *camera);
144
145// Camera movement
146RLAPI void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane);
147RLAPI void CameraMoveUp(Camera *camera, float distance);
148RLAPI void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane);
149RLAPI void CameraMoveToTarget(Camera *camera, float delta);
150
151// Camera rotation
152RLAPI void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget);
153RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp);
154RLAPI void CameraRoll(Camera *camera, float angle);
155
156RLAPI Matrix GetCameraViewMatrix(Camera *camera);
157RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
158
159#if defined(__cplusplus)
160}
161#endif
162
163#endif // RCAMERA_H
164
165/***********************************************************************************
166*
167* CAMERA IMPLEMENTATION
168*
169************************************************************************************/
170
171#if defined(RCAMERA_IMPLEMENTATION)
172
173#include "raymath.h" // Required for vector maths:
174 // Vector3Add()
175 // Vector3Subtract()
176 // Vector3Scale()
177 // Vector3Normalize()
178 // Vector3Distance()
179 // Vector3CrossProduct()
180 // Vector3RotateByAxisAngle()
181 // Vector3Angle()
182 // Vector3Negate()
183 // MatrixLookAt()
184 // MatrixPerspective()
185 // MatrixOrtho()
186 // MatrixIdentity()
187
188// raylib required functionality:
189 // GetMouseDelta()
190 // GetMouseWheelMove()
191 // IsKeyDown()
192 // IsKeyPressed()
193 // GetFrameTime()
194
195//----------------------------------------------------------------------------------
196// Defines and Macros
197//----------------------------------------------------------------------------------
198#define CAMERA_MOVE_SPEED 5.4f // Units per second
199#define CAMERA_ROTATION_SPEED 0.03f
200#define CAMERA_PAN_SPEED 0.2f
201
202// Camera mouse movement sensitivity
203#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f
204
205// Camera orbital speed in CAMERA_ORBITAL mode
206#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
207
208//----------------------------------------------------------------------------------
209// Types and Structures Definition
210//----------------------------------------------------------------------------------
211//...
212
213//----------------------------------------------------------------------------------
214// Global Variables Definition
215//----------------------------------------------------------------------------------
216//...
217
218//----------------------------------------------------------------------------------
219// Module specific Functions Declaration
220//----------------------------------------------------------------------------------
221//...
222
223//----------------------------------------------------------------------------------
224// Module Functions Definition
225//----------------------------------------------------------------------------------
226// Returns the cameras forward vector (normalized)
227Vector3 GetCameraForward(Camera *camera)
228{
229 return Vector3Normalize(Vector3Subtract(camera->target, camera->position));
230}
231
232// Returns the cameras up vector (normalized)
233// Note: The up vector might not be perpendicular to the forward vector
234Vector3 GetCameraUp(Camera *camera)
235{
236 return Vector3Normalize(camera->up);
237}
238
239// Returns the cameras right vector (normalized)
240Vector3 GetCameraRight(Camera *camera)
241{
242 Vector3 forward = GetCameraForward(camera);
243 Vector3 up = GetCameraUp(camera);
244
245 return Vector3Normalize(Vector3CrossProduct(forward, up));
246}
247
248// Moves the camera in its forward direction
249void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane)
250{
251 Vector3 forward = GetCameraForward(camera);
252
253 if (moveInWorldPlane)
254 {
255 // Project vector onto world plane
256 forward.y = 0;
257 forward = Vector3Normalize(forward);
258 }
259
260 // Scale by distance
261 forward = Vector3Scale(forward, distance);
262
263 // Move position and target
264 camera->position = Vector3Add(camera->position, forward);
265 camera->target = Vector3Add(camera->target, forward);
266}
267
268// Moves the camera in its up direction
269void CameraMoveUp(Camera *camera, float distance)
270{
271 Vector3 up = GetCameraUp(camera);
272
273 // Scale by distance
274 up = Vector3Scale(up, distance);
275
276 // Move position and target
277 camera->position = Vector3Add(camera->position, up);
278 camera->target = Vector3Add(camera->target, up);
279}
280
281// Moves the camera target in its current right direction
282void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane)
283{
284 Vector3 right = GetCameraRight(camera);
285
286 if (moveInWorldPlane)
287 {
288 // Project vector onto world plane
289 right.y = 0;
290 right = Vector3Normalize(right);
291 }
292
293 // Scale by distance
294 right = Vector3Scale(right, distance);
295
296 // Move position and target
297 camera->position = Vector3Add(camera->position, right);
298 camera->target = Vector3Add(camera->target, right);
299}
300
301// Moves the camera position closer/farther to/from the camera target
302void CameraMoveToTarget(Camera *camera, float delta)
303{
304 float distance = Vector3Distance(camera->position, camera->target);
305
306 // Apply delta
307 distance += delta;
308
309 // Distance must be greater than 0
310 if (distance <= 0) distance = 0.001f;
311
312 // Set new distance by moving the position along the forward vector
313 Vector3 forward = GetCameraForward(camera);
314 camera->position = Vector3Add(camera->target, Vector3Scale(forward, -distance));
315}
316
317// Rotates the camera around its up vector
318// Yaw is "looking left and right"
319// If rotateAroundTarget is false, the camera rotates around its position
320// Note: angle must be provided in radians
321void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget)
322{
323 // Rotation axis
324 Vector3 up = GetCameraUp(camera);
325
326 // View vector
327 Vector3 targetPosition = Vector3Subtract(camera->target, camera->position);
328
329 // Rotate view vector around up axis
330 targetPosition = Vector3RotateByAxisAngle(targetPosition, up, angle);
331
332 if (rotateAroundTarget)
333 {
334 // Move position relative to target
335 camera->position = Vector3Subtract(camera->target, targetPosition);
336 }
337 else // rotate around camera.position
338 {
339 // Move target relative to position
340 camera->target = Vector3Add(camera->position, targetPosition);
341 }
342}
343
344// Rotates the camera around its right vector, pitch is "looking up and down"
345// - lockView prevents camera overrotation (aka "somersaults")
346// - rotateAroundTarget defines if rotation is around target or around its position
347// - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE)
348// NOTE: angle must be provided in radians
349void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp)
350{
351 // Up direction
352 Vector3 up = GetCameraUp(camera);
353
354 // View vector
355 Vector3 targetPosition = Vector3Subtract(camera->target, camera->position);
356
357 if (lockView)
358 {
359 // In these camera modes we clamp the Pitch angle
360 // to allow only viewing straight up or down.
361
362 // Clamp view up
363 float maxAngleUp = Vector3Angle(up, targetPosition);
364 maxAngleUp -= 0.001f; // avoid numerical errors
365 if (angle > maxAngleUp) angle = maxAngleUp;
366
367 // Clamp view down
368 float maxAngleDown = Vector3Angle(Vector3Negate(up), targetPosition);
369 maxAngleDown *= -1.0f; // downwards angle is negative
370 maxAngleDown += 0.001f; // avoid numerical errors
371 if (angle < maxAngleDown) angle = maxAngleDown;
372 }
373
374 // Rotation axis
375 Vector3 right = GetCameraRight(camera);
376
377 // Rotate view vector around right axis
378 targetPosition = Vector3RotateByAxisAngle(targetPosition, right, angle);
379
380 if (rotateAroundTarget)
381 {
382 // Move position relative to target
383 camera->position = Vector3Subtract(camera->target, targetPosition);
384 }
385 else // rotate around camera.position
386 {
387 // Move target relative to position
388 camera->target = Vector3Add(camera->position, targetPosition);
389 }
390
391 if (rotateUp)
392 {
393 // Rotate up direction around right axis
394 camera->up = Vector3RotateByAxisAngle(camera->up, right, angle);
395 }
396}
397
398// Rotates the camera around its forward vector
399// Roll is "turning your head sideways to the left or right"
400// Note: angle must be provided in radians
401void CameraRoll(Camera *camera, float angle)
402{
403 // Rotation axis
404 Vector3 forward = GetCameraForward(camera);
405
406 // Rotate up direction around forward axis
407 camera->up = Vector3RotateByAxisAngle(camera->up, forward, angle);
408}
409
410// Returns the camera view matrix
411Matrix GetCameraViewMatrix(Camera *camera)
412{
413 return MatrixLookAt(camera->position, camera->target, camera->up);
414}
415
416// Returns the camera projection matrix
417Matrix GetCameraProjectionMatrix(Camera *camera, float aspect)
418{
419 if (camera->projection == CAMERA_PERSPECTIVE)
420 {
421 return MatrixPerspective(camera->fovy*DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR);
422 }
423 else if (camera->projection == CAMERA_ORTHOGRAPHIC)
424 {
425 double top = camera->fovy/2.0;
426 double right = top*aspect;
427
428 return MatrixOrtho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR);
429 }
430
431 return MatrixIdentity();
432}
433
434#if !defined(RCAMERA_STANDALONE)
435// Update camera position for selected mode
436// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
437void UpdateCamera(Camera *camera, int mode)
438{
439 Vector2 mousePositionDelta = GetMouseDelta();
440
441 bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
442 bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
443 bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
444 bool rotateUp = false;
445
446 // Camera speeds based on frame time
447 float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime();
448 float cameraRotationSpeed = CAMERA_ROTATION_SPEED*GetFrameTime();
449 float cameraPanSpeed = CAMERA_PAN_SPEED*GetFrameTime();
450 float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime();
451
452 if (mode == CAMERA_CUSTOM) {}
453 else if (mode == CAMERA_ORBITAL)
454 {
455 // Orbital can just orbit
456 Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed);
457 Vector3 view = Vector3Subtract(camera->position, camera->target);
458 view = Vector3Transform(view, rotation);
459 camera->position = Vector3Add(camera->target, view);
460 }
461 else
462 {
463 // Camera rotation
464 if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
465 if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
466 if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget);
467 if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget);
468 if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed);
469 if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed);
470
471 // Camera movement
472 // Camera pan (for CAMERA_FREE)
473 if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
474 {
475 const Vector2 mouseDelta = GetMouseDelta();
476 if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane);
477 if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane);
478 if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed);
479 if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed);
480 }
481 else
482 {
483 // Mouse support
484 CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
485 CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
486 }
487
488 // Keyboard support
489 if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
490 if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
491 if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
492 if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
493
494 // Gamepad movement
495 if (IsGamepadAvailable(0))
496 {
497 // Gamepad controller support
498 CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
499 CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
500
501 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
502 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
503 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
504 if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
505 }
506
507 if (mode == CAMERA_FREE)
508 {
509 if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed);
510 if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -cameraMoveSpeed);
511 }
512 }
513
514 if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE))
515 {
516 // Zoom target distance
517 CameraMoveToTarget(camera, -GetMouseWheelMove());
518 if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f);
519 if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
520 }
521}
522#endif // !RCAMERA_STANDALONE
523
524// Update camera movement, movement/rotation values should be provided by user
525void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
526{
527 // Required values
528 // movement.x - Move forward/backward
529 // movement.y - Move right/left
530 // movement.z - Move up/down
531 // rotation.x - yaw
532 // rotation.y - pitch
533 // rotation.z - roll
534 // zoom - Move towards target
535
536 bool lockView = true;
537 bool rotateAroundTarget = false;
538 bool rotateUp = false;
539 bool moveInWorldPlane = true;
540
541 // Camera rotation
542 CameraPitch(camera, -rotation.y*DEG2RAD, lockView, rotateAroundTarget, rotateUp);
543 CameraYaw(camera, -rotation.x*DEG2RAD, rotateAroundTarget);
544 CameraRoll(camera, rotation.z*DEG2RAD);
545
546 // Camera movement
547 CameraMoveForward(camera, movement.x, moveInWorldPlane);
548 CameraMoveRight(camera, movement.y, moveInWorldPlane);
549 CameraMoveUp(camera, movement.z);
550
551 // Zoom target distance
552 CameraMoveToTarget(camera, zoom);
553}
554
555#endif // RCAMERA_IMPLEMENTATION

Generated with cgit - Back to sebastiano.tronto.net