gencpp/project/auxillary/vis_ast/dependencies/raylib/include/rcamera.h

559 lines
22 KiB
C

/*******************************************************************************************
*
* rcamera - Basic camera system with support for multiple camera modes
*
* CONFIGURATION:
* #define RCAMERA_IMPLEMENTATION
* Generates the implementation of the library into the included file.
* If not defined, the library is in header only mode and can be included in other headers
* or source files without problems. But only ONE file should hold the implementation.
*
* #define RCAMERA_STANDALONE
* If defined, the library can be used as standalone as a camera system but some
* functions must be redefined to manage inputs accordingly.
*
* CONTRIBUTORS:
* Ramon Santamaria: Supervision, review, update and maintenance
* Christoph Wagner: Complete redesign, using raymath (2022)
* Marc Palau: Initial implementation (2014)
*
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2022-2023 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef RCAMERA_H
#define RCAMERA_H
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Function specifiers definition
// Function specifiers in case library is build/used as a shared library (Windows)
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
#if defined(_WIN32)
#if defined(RL_BUILD_LIBTYPE_SHARED)
#if defined(__TINYC__)
#define __declspec(x) __attribute__((x))
#endif
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
#elif defined(RL_USE_LIBTYPE_SHARED)
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
#endif
#endif
#ifndef RLAPI
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
#endif
#if defined(RCAMERA_STANDALONE)
#define RL_CAMERA_CULL_DISTANCE_NEAR 0.01
#define RL_CAMERA_CULL_DISTANCE_FAR 1000.0
#else
#define RL_CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR
#define RL_CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
// NOTE: Below types are required for standalone usage
//----------------------------------------------------------------------------------
#if defined(RCAMERA_STANDALONE)
// RL_Vector2, 2 components
typedef struct RL_Vector2 {
float x; // Vector x component
float y; // Vector y component
} RL_Vector2;
// RL_Vector3, 3 components
typedef struct RL_Vector3 {
float x; // Vector x component
float y; // Vector y component
float z; // Vector z component
} RL_Vector3;
// RL_Matrix, 4x4 components, column major, OpenGL style, right-handed
typedef struct RL_Matrix {
float m0, m4, m8, m12; // RL_Matrix first row (4 components)
float m1, m5, m9, m13; // RL_Matrix second row (4 components)
float m2, m6, m10, m14; // RL_Matrix third row (4 components)
float m3, m7, m11, m15; // RL_Matrix fourth row (4 components)
} RL_Matrix;
// RL_Camera type, defines a camera position/orientation in 3d space
typedef struct RL_Camera3D {
RL_Vector3 position; // RL_Camera position
RL_Vector3 target; // RL_Camera target it looks-at
RL_Vector3 up; // RL_Camera up vector (rotation over its axis)
float fovy; // RL_Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
int projection; // RL_Camera projection type: RL_CAMERA_PERSPECTIVE or RL_CAMERA_ORTHOGRAPHIC
} RL_Camera3D;
typedef RL_Camera3D RL_Camera; // RL_Camera type fallback, defaults to RL_Camera3D
// RL_Camera projection
typedef enum {
RL_CAMERA_PERSPECTIVE = 0, // Perspective projection
RL_CAMERA_ORTHOGRAPHIC // Orthographic projection
} RL_CameraProjection;
// RL_Camera system modes
typedef enum {
RL_CAMERA_CUSTOM = 0, // RL_Camera custom, controlled by user (RL_UpdateCamera() does nothing)
RL_CAMERA_FREE, // RL_Camera free mode
RL_CAMERA_ORBITAL, // RL_Camera orbital, around target, zoom supported
RL_CAMERA_FIRST_PERSON, // RL_Camera first person
RL_CAMERA_THIRD_PERSON // RL_Camera third person
} RL_CameraMode;
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
#if defined(__cplusplus)
extern "C" { // Prevents name mangling of functions
#endif
RLAPI RL_Vector3 GetCameraForward(RL_Camera *camera);
RLAPI RL_Vector3 GetCameraUp(RL_Camera *camera);
RLAPI RL_Vector3 GetCameraRight(RL_Camera *camera);
// RL_Camera movement
RLAPI void CameraMoveForward(RL_Camera *camera, float distance, bool moveInWorldPlane);
RLAPI void CameraMoveUp(RL_Camera *camera, float distance);
RLAPI void CameraMoveRight(RL_Camera *camera, float distance, bool moveInWorldPlane);
RLAPI void CameraMoveToTarget(RL_Camera *camera, float delta);
// RL_Camera rotation
RLAPI void CameraYaw(RL_Camera *camera, float angle, bool rotateAroundTarget);
RLAPI void CameraPitch(RL_Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp);
RLAPI void CameraRoll(RL_Camera *camera, float angle);
RLAPI RL_Matrix GetCameraViewMatrix(RL_Camera *camera);
RLAPI RL_Matrix GetCameraProjectionMatrix(RL_Camera* camera, float aspect);
#if defined(__cplusplus)
}
#endif
#endif // RCAMERA_H
/***********************************************************************************
*
* CAMERA IMPLEMENTATION
*
************************************************************************************/
#if defined(RCAMERA_IMPLEMENTATION)
#include "raymath.h" // Required for vector maths:
// RL_Vector3Add()
// RL_Vector3Subtract()
// RL_Vector3Scale()
// RL_Vector3Normalize()
// RL_Vector3Distance()
// RL_Vector3CrossProduct()
// RL_Vector3RotateByAxisAngle()
// RL_Vector3Angle()
// RL_Vector3Negate()
// RL_MatrixLookAt()
// RL_MatrixPerspective()
// RL_MatrixOrtho()
// RL_MatrixIdentity()
// raylib required functionality:
// RL_GetMouseDelta()
// RL_GetMouseWheelMove()
// RL_IsKeyDown()
// RL_IsKeyPressed()
// RL_GetFrameTime()
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define RL_CAMERA_MOVE_SPEED 0.09f
#define RL_CAMERA_ROTATION_SPEED 0.03f
#define RL_CAMERA_PAN_SPEED 0.2f
// RL_Camera mouse movement sensitivity
#define RL_CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
#define RL_CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
#define RL_CAMERA_ORBITAL_SPEED 0.5f // Radians per second
#define RL_CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 8.0f
#define RL_CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f
#define RL_CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f
// PLAYER (used by camera)
#define RL_PLAYER_MOVEMENT_SENSITIVITY 20.0f
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Returns the cameras forward vector (normalized)
RL_Vector3 GetCameraForward(RL_Camera *camera)
{
return RL_Vector3Normalize(RL_Vector3Subtract(camera->target, camera->position));
}
// Returns the cameras up vector (normalized)
// Note: The up vector might not be perpendicular to the forward vector
RL_Vector3 GetCameraUp(RL_Camera *camera)
{
return RL_Vector3Normalize(camera->up);
}
// Returns the cameras right vector (normalized)
RL_Vector3 GetCameraRight(RL_Camera *camera)
{
RL_Vector3 forward = GetCameraForward(camera);
RL_Vector3 up = GetCameraUp(camera);
return RL_Vector3CrossProduct(forward, up);
}
// Moves the camera in its forward direction
void CameraMoveForward(RL_Camera *camera, float distance, bool moveInWorldPlane)
{
RL_Vector3 forward = GetCameraForward(camera);
if (moveInWorldPlane)
{
// Project vector onto world plane
forward.y = 0;
forward = RL_Vector3Normalize(forward);
}
// Scale by distance
forward = RL_Vector3Scale(forward, distance);
// Move position and target
camera->position = RL_Vector3Add(camera->position, forward);
camera->target = RL_Vector3Add(camera->target, forward);
}
// Moves the camera in its up direction
void CameraMoveUp(RL_Camera *camera, float distance)
{
RL_Vector3 up = GetCameraUp(camera);
// Scale by distance
up = RL_Vector3Scale(up, distance);
// Move position and target
camera->position = RL_Vector3Add(camera->position, up);
camera->target = RL_Vector3Add(camera->target, up);
}
// Moves the camera target in its current right direction
void CameraMoveRight(RL_Camera *camera, float distance, bool moveInWorldPlane)
{
RL_Vector3 right = GetCameraRight(camera);
if (moveInWorldPlane)
{
// Project vector onto world plane
right.y = 0;
right = RL_Vector3Normalize(right);
}
// Scale by distance
right = RL_Vector3Scale(right, distance);
// Move position and target
camera->position = RL_Vector3Add(camera->position, right);
camera->target = RL_Vector3Add(camera->target, right);
}
// Moves the camera position closer/farther to/from the camera target
void CameraMoveToTarget(RL_Camera *camera, float delta)
{
float distance = RL_Vector3Distance(camera->position, camera->target);
// Apply delta
distance += delta;
// Distance must be greater than 0
if (distance <= 0) distance = 0.001f;
// Set new distance by moving the position along the forward vector
RL_Vector3 forward = GetCameraForward(camera);
camera->position = RL_Vector3Add(camera->target, RL_Vector3Scale(forward, -distance));
}
// Rotates the camera around its up vector
// Yaw is "looking left and right"
// If rotateAroundTarget is false, the camera rotates around its position
// Note: angle must be provided in radians
void CameraYaw(RL_Camera *camera, float angle, bool rotateAroundTarget)
{
// Rotation axis
RL_Vector3 up = GetCameraUp(camera);
// View vector
RL_Vector3 targetPosition = RL_Vector3Subtract(camera->target, camera->position);
// Rotate view vector around up axis
targetPosition = RL_Vector3RotateByAxisAngle(targetPosition, up, angle);
if (rotateAroundTarget)
{
// Move position relative to target
camera->position = RL_Vector3Subtract(camera->target, targetPosition);
}
else // rotate around camera.position
{
// Move target relative to position
camera->target = RL_Vector3Add(camera->position, targetPosition);
}
}
// Rotates the camera around its right vector, pitch is "looking up and down"
// - lockView prevents camera overrotation (aka "somersaults")
// - rotateAroundTarget defines if rotation is around target or around its position
// - rotateUp rotates the up direction as well (typically only usefull in RL_CAMERA_FREE)
// NOTE: angle must be provided in radians
void CameraPitch(RL_Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp)
{
// Up direction
RL_Vector3 up = GetCameraUp(camera);
// View vector
RL_Vector3 targetPosition = RL_Vector3Subtract(camera->target, camera->position);
if (lockView)
{
// In these camera modes we clamp the Pitch angle
// to allow only viewing straight up or down.
// RL_Clamp view up
float maxAngleUp = RL_Vector3Angle(up, targetPosition);
maxAngleUp -= 0.001f; // avoid numerical errors
if (angle > maxAngleUp) angle = maxAngleUp;
// RL_Clamp view down
float maxAngleDown = RL_Vector3Angle(RL_Vector3Negate(up), targetPosition);
maxAngleDown *= -1.0f; // downwards angle is negative
maxAngleDown += 0.001f; // avoid numerical errors
if (angle < maxAngleDown) angle = maxAngleDown;
}
// Rotation axis
RL_Vector3 right = GetCameraRight(camera);
// Rotate view vector around right axis
targetPosition = RL_Vector3RotateByAxisAngle(targetPosition, right, angle);
if (rotateAroundTarget)
{
// Move position relative to target
camera->position = RL_Vector3Subtract(camera->target, targetPosition);
}
else // rotate around camera.position
{
// Move target relative to position
camera->target = RL_Vector3Add(camera->position, targetPosition);
}
if (rotateUp)
{
// Rotate up direction around right axis
camera->up = RL_Vector3RotateByAxisAngle(camera->up, right, angle);
}
}
// Rotates the camera around its forward vector
// Roll is "turning your head sideways to the left or right"
// Note: angle must be provided in radians
void CameraRoll(RL_Camera *camera, float angle)
{
// Rotation axis
RL_Vector3 forward = GetCameraForward(camera);
// Rotate up direction around forward axis
camera->up = RL_Vector3RotateByAxisAngle(camera->up, forward, angle);
}
// Returns the camera view matrix
RL_Matrix GetCameraViewMatrix(RL_Camera *camera)
{
return RL_MatrixLookAt(camera->position, camera->target, camera->up);
}
// Returns the camera projection matrix
RL_Matrix GetCameraProjectionMatrix(RL_Camera *camera, float aspect)
{
if (camera->projection == RL_CAMERA_PERSPECTIVE)
{
return RL_MatrixPerspective(camera->fovy*RL_DEG2RAD, aspect, RL_CAMERA_CULL_DISTANCE_NEAR, RL_CAMERA_CULL_DISTANCE_FAR);
}
else if (camera->projection == RL_CAMERA_ORTHOGRAPHIC)
{
double top = camera->fovy/2.0;
double right = top*aspect;
return RL_MatrixOrtho(-right, right, -top, top, RL_CAMERA_CULL_DISTANCE_NEAR, RL_CAMERA_CULL_DISTANCE_FAR);
}
return RL_MatrixIdentity();
}
#if !defined(RCAMERA_STANDALONE)
// Update camera position for selected mode
// RL_Camera mode: RL_CAMERA_FREE, RL_CAMERA_FIRST_PERSON, RL_CAMERA_THIRD_PERSON, RL_CAMERA_ORBITAL or CUSTOM
void RL_UpdateCamera(RL_Camera *camera, int mode)
{
RL_Vector2 mousePositionDelta = RL_GetMouseDelta();
bool moveInWorldPlane = ((mode == RL_CAMERA_FIRST_PERSON) || (mode == RL_CAMERA_THIRD_PERSON));
bool rotateAroundTarget = ((mode == RL_CAMERA_THIRD_PERSON) || (mode == RL_CAMERA_ORBITAL));
bool lockView = ((mode == RL_CAMERA_FIRST_PERSON) || (mode == RL_CAMERA_THIRD_PERSON) || (mode == RL_CAMERA_ORBITAL));
bool rotateUp = false;
if (mode == RL_CAMERA_ORBITAL)
{
// Orbital can just orbit
RL_Matrix rotation = RL_MatrixRotate(GetCameraUp(camera), RL_CAMERA_ORBITAL_SPEED*RL_GetFrameTime());
RL_Vector3 view = RL_Vector3Subtract(camera->position, camera->target);
view = RL_Vector3Transform(view, rotation);
camera->position = RL_Vector3Add(camera->target, view);
}
else
{
// RL_Camera rotation
if (RL_IsKeyDown(RL_KEY_DOWN)) CameraPitch(camera, -RL_CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
if (RL_IsKeyDown(RL_KEY_UP)) CameraPitch(camera, RL_CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
if (RL_IsKeyDown(RL_KEY_RIGHT)) CameraYaw(camera, -RL_CAMERA_ROTATION_SPEED, rotateAroundTarget);
if (RL_IsKeyDown(RL_KEY_LEFT)) CameraYaw(camera, RL_CAMERA_ROTATION_SPEED, rotateAroundTarget);
if (RL_IsKeyDown(RL_KEY_Q)) CameraRoll(camera, -RL_CAMERA_ROTATION_SPEED);
if (RL_IsKeyDown(RL_KEY_E)) CameraRoll(camera, RL_CAMERA_ROTATION_SPEED);
// RL_Camera movement
if (!RL_IsGamepadAvailable(0))
{
// RL_Camera pan (for RL_CAMERA_FREE)
if ((mode == RL_CAMERA_FREE) && (RL_IsMouseButtonDown(RL_MOUSE_BUTTON_MIDDLE)))
{
const RL_Vector2 mouseDelta = RL_GetMouseDelta();
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, RL_CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -RL_CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -RL_CAMERA_PAN_SPEED);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, RL_CAMERA_PAN_SPEED);
}
else
{
// Mouse support
CameraYaw(camera, -mousePositionDelta.x*RL_CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -mousePositionDelta.y*RL_CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
}
// Keyboard support
if (RL_IsKeyDown(RL_KEY_W)) CameraMoveForward(camera, RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
if (RL_IsKeyDown(RL_KEY_A)) CameraMoveRight(camera, -RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
if (RL_IsKeyDown(RL_KEY_S)) CameraMoveForward(camera, -RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
if (RL_IsKeyDown(RL_KEY_D)) CameraMoveRight(camera, RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
}
else
{
// Gamepad controller support
CameraYaw(camera, -(RL_GetGamepadAxisMovement(0, RL_GAMEPAD_AXIS_RIGHT_X) * 2)*RL_CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -(RL_GetGamepadAxisMovement(0, RL_GAMEPAD_AXIS_RIGHT_Y) * 2)*RL_CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
if (RL_GetGamepadAxisMovement(0, RL_GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
if (RL_GetGamepadAxisMovement(0, RL_GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
if (RL_GetGamepadAxisMovement(0, RL_GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
if (RL_GetGamepadAxisMovement(0, RL_GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, RL_CAMERA_MOVE_SPEED, moveInWorldPlane);
}
if (mode == RL_CAMERA_FREE)
{
if (RL_IsKeyDown(RL_KEY_SPACE)) CameraMoveUp(camera, RL_CAMERA_MOVE_SPEED);
if (RL_IsKeyDown(RL_KEY_LEFT_CONTROL)) CameraMoveUp(camera, -RL_CAMERA_MOVE_SPEED);
}
}
if ((mode == RL_CAMERA_THIRD_PERSON) || (mode == RL_CAMERA_ORBITAL) || (mode == RL_CAMERA_FREE))
{
// Zoom target distance
CameraMoveToTarget(camera, -RL_GetMouseWheelMove());
if (RL_IsKeyPressed(RL_KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f);
if (RL_IsKeyPressed(RL_KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
}
}
#endif // !RCAMERA_STANDALONE
// Update camera movement, movement/rotation values should be provided by user
void RL_UpdateCameraPro(RL_Camera *camera, RL_Vector3 movement, RL_Vector3 rotation, float zoom)
{
// Required values
// movement.x - Move forward/backward
// movement.y - Move right/left
// movement.z - Move up/down
// rotation.x - yaw
// rotation.y - pitch
// rotation.z - roll
// zoom - Move towards target
bool lockView = true;
bool rotateAroundTarget = false;
bool rotateUp = false;
bool moveInWorldPlane = true;
// RL_Camera rotation
CameraPitch(camera, -rotation.y*RL_DEG2RAD, lockView, rotateAroundTarget, rotateUp);
CameraYaw(camera, -rotation.x*RL_DEG2RAD, rotateAroundTarget);
CameraRoll(camera, rotation.z*RL_DEG2RAD);
// RL_Camera movement
CameraMoveForward(camera, movement.x, moveInWorldPlane);
CameraMoveRight(camera, movement.y, moveInWorldPlane);
CameraMoveUp(camera, movement.z);
// Zoom target distance
CameraMoveToTarget(camera, zoom);
}
#endif // RCAMERA_IMPLEMENTATION