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 |
|
|
|