diff options
| -rw-r--r-- | API.md | 118 | ||||
| -rw-r--r-- | ReiLua_API.lua | 108 | ||||
| -rw-r--r-- | changelog | 13 | ||||
| -rw-r--r-- | examples/ReiLuaGui_examples/main.lua | 2 | ||||
| -rw-r--r-- | examples/heightmap/main.lua | 40 | ||||
| -rw-r--r-- | examples/lightmap/main.lua | 4 | ||||
| -rw-r--r-- | include/core.h | 17 | ||||
| -rw-r--r-- | include/main.h | 1 | ||||
| -rw-r--r-- | include/rcamera.h | 504 | ||||
| -rw-r--r-- | src/core.c | 339 | ||||
| -rw-r--r-- | src/lua_core.c | 17 |
11 files changed, 1142 insertions, 21 deletions
@@ -2394,6 +2394,124 @@ Get camera projection mode --- +> forward = RL.GetCamera3DForward( camera3D camera ) + +Returns the cameras forward vector ( normalized ) + +- Failure return nil +- Success return Vector3 + +--- + +> up = RL.GetCamera3DUpNormalized( camera3D camera ) + +Returns the cameras up vector ( normalized ) +Note: The up vector might not be perpendicular to the forward vector + +- Failure return nil +- Success return Vector3 + +--- + +> forward = RL.GetCamera3DRight( camera3D camera ) + +Returns the cameras right vector ( normalized ) + +- Failure return nil +- Success return Vector3 + +--- + +> success = RL.Camera3DMoveForward( camera3D camera, float distance, bool moveInWorldPlane ) + +Moves the camera in it's forward direction + +- Failure return false +- Success return true + +--- + +> success = RL.Camera3DMoveUp( camera3D camera, float distance ) + +Moves the camera in it's up direction + +- Failure return false +- Success return true + +--- + +> success = RL.Camera3DMoveRight( camera3D camera, float distance, bool moveInWorldPlane ) + +Moves the camera target in it's current right direction + +- Failure return false +- Success return true + +--- + +> success = RL.Camera3DMoveToTarget( camera3D camera, float delta ) + +Moves the camera position closer/farther to/from the camera target + +- Failure return false +- Success return true + +--- + +> success = RL.Camera3DYaw( camera3D camera, float angle, bool rotateAroundTarget ) + +Rotates the camera around it's up vector +Yaw is "looking left and right" +If rotateAroundTarget is false, the camera rotates around it's position +Note: angle must be provided in radians + +- Failure return false +- Success return true + +--- + +> success = RL.Camera3DPitch( camera3D camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp ) + +Rotates the camera around it's right vector, pitch is "looking up and down" + - lockView prevents camera overrotation (aka "somersaults") + - rotateAroundTarget defines if rotation is around target or around it's position + - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) +NOTE: angle must be provided in radians + +- Failure return false +- Success return true + +--- + +> success = RL.Camera3DRoll( camera3D camera, float angle ) + +Rotates the camera around it's forward vector +Roll is "turning your head sideways to the left or right" +Note: angle must be provided in radians + +- Failure return false +- Success return true + +--- + +> view = RL.GetCamera3DViewMatrix( camera3D camera ) + +Returns the camera view matrix + +- Failure return false +- Success return Matrix + +--- + +> projection = RL.GetCamera3DProjectionMatrix( camera3D camera, float aspect ) + +Returns the camera projection matrix + +- Failure return false +- Success return Matrix + +--- + > success = RL.UpdateCamera3D( camera3D camera, int mode ) Update camera position for selected mode diff --git a/ReiLua_API.lua b/ReiLua_API.lua index c6c5b7e..fe1cd0e 100644 --- a/ReiLua_API.lua +++ b/ReiLua_API.lua @@ -1531,6 +1531,114 @@ function RL.GetCamera3DFovy( camera ) end ---@return any projection function RL.GetCamera3DProjection( camera ) end +---Returns the cameras forward vector ( normalized ) +---- Failure return nil +---- Success return Vector3 +---@param camera any +---@return any forward +function RL.GetCamera3DForward( camera ) end + +---Returns the cameras up vector ( normalized ) +---Note: The up vector might not be perpendicular to the forward vector +---- Failure return nil +---- Success return Vector3 +---@param camera any +---@return any up +function RL.GetCamera3DUpNormalized( camera ) end + +---Returns the cameras right vector ( normalized ) +---- Failure return nil +---- Success return Vector3 +---@param camera any +---@return any forward +function RL.GetCamera3DRight( camera ) end + +---Moves the camera in it's forward direction +---- Failure return false +---- Success return true +---@param camera any +---@param distance number +---@param moveInWorldPlane boolean +---@return any success +function RL.Camera3DMoveForward( camera, distance, moveInWorldPlane ) end + +---Moves the camera in it's up direction +---- Failure return false +---- Success return true +---@param camera any +---@param distance number +---@return any success +function RL.Camera3DMoveUp( camera, distance ) end + +---Moves the camera target in it's current right direction +---- Failure return false +---- Success return true +---@param camera any +---@param distance number +---@param moveInWorldPlane boolean +---@return any success +function RL.Camera3DMoveRight( camera, distance, moveInWorldPlane ) end + +---Moves the camera position closer/farther to/from the camera target +---- Failure return false +---- Success return true +---@param camera any +---@param delta number +---@return any success +function RL.Camera3DMoveToTarget( camera, delta ) end + +---Rotates the camera around it's up vector +---Yaw is "looking left and right" +---If rotateAroundTarget is false, the camera rotates around it's position +---Note: angle must be provided in radians +---- Failure return false +---- Success return true +---@param camera any +---@param angle number +---@param rotateAroundTarget boolean +---@return any success +function RL.Camera3DYaw( camera, angle, rotateAroundTarget ) end + +---Rotates the camera around it's right vector, pitch is "looking up and down" +--- - lockView prevents camera overrotation (aka "somersaults") +--- - rotateAroundTarget defines if rotation is around target or around it's position +--- - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) +---NOTE: angle must be provided in radians +---- Failure return false +---- Success return true +---@param camera any +---@param angle number +---@param lockView boolean +---@param rotateAroundTarget boolean +---@param rotateUp boolean +---@return any success +function RL.Camera3DPitch( camera, angle, lockView, rotateAroundTarget, rotateUp ) end + +---Rotates the camera around it's forward vector +---Roll is "turning your head sideways to the left or right" +---Note: angle must be provided in radians +---- Failure return false +---- Success return true +---@param camera any +---@param angle number +---@return any success +function RL.Camera3DRoll( camera, angle ) end + +---Returns the camera view matrix +---- Failure return false +---- Success return Matrix +---@param camera any +---@return any view +function RL.GetCamera3DViewMatrix( camera ) end + +---Returns the camera projection matrix +---- Failure return false +---- Success return Matrix +---@param camera any +---@param aspect number +---@return any projection +function RL.GetCamera3DProjectionMatrix( camera, aspect ) end + ---Update camera position for selected mode ---- Failure return false ---- Success return true @@ -8,6 +8,7 @@ KEY CHANGES: - CHANGED: Switched to Raylib vertion 4.5. Removed some functions and added others. Main changes to camera3D. - REVISED: How Lua argumets are handled. Now uluaGet*Index functions can take stack index(positive only). Also using positive stack indexing. + - ADDED: Camera3D Lua lib. Detailed changes: - FIXED: uluaGetRay was looking for integers instead of tables. @@ -36,6 +37,18 @@ Detailed changes: - CHANGED: DrawTriangleFan no longer require pointsCount - CHANGED: DrawTriangleStrip no longer require pointsCount - FIXED: LoadShaderFromMemory + - ADDED: GetCamera3DForward + - ADDED: GetCamera3DUpNormalized + - ADDED: GetCamera3DRight + - ADDED: Camera3DMoveForward + - ADDED: Camera3DMoveUp + - ADDED: Camera3DMoveRight + - ADDED: Camera3DMoveToTarget + - ADDED: Camera3DYaw + - ADDED: Camera3DPitch + - ADDED: Camera3DRoll + - ADDED: GetCamera3DViewMatrix + - ADDED: GetCamera3DProjectionMatrix ------------------------------------------------------------------------ Release: ReiLua version 0.4.0 Using Raylib 4.2 diff --git a/examples/ReiLuaGui_examples/main.lua b/examples/ReiLuaGui_examples/main.lua index 29dace8..3c120b5 100644 --- a/examples/ReiLuaGui_examples/main.lua +++ b/examples/ReiLuaGui_examples/main.lua @@ -1,7 +1,7 @@ package.path = package.path..";"..RL.GetBasePath().."?.lua" package.path = package.path..";"..RL.GetBasePath().."../resources/lib/?.lua" -util = require( "utillib" ) +Util = require( "utillib" ) Vec2 = require( "vector2" ) Rect = require( "rectangle" ) Color = require( "color" ) diff --git a/examples/heightmap/main.lua b/examples/heightmap/main.lua index d046d2a..eb660b3 100644 --- a/examples/heightmap/main.lua +++ b/examples/heightmap/main.lua @@ -1,7 +1,14 @@ +package.path = package.path..";"..RL.GetBasePath().."../resources/lib/?.lua" + +Util = require( "utillib" ) +Vec2 = require( "vector2" ) +Vec3 = require( "vector3" ) +Cam3D = require( "camera3d" ) + local TILE_SIZE = 32 local monitor = 0 -local camera = -1 +local camera = {} local groundTexture = -1 local tilesetTex = -1 local heigthImage = -1 @@ -27,11 +34,14 @@ function RL.init() RL.SetWindowState( RL.FLAG_VSYNC_HINT ) RL.SetWindowPosition( { mPos[1] + mSize[1] / 2 - winSize[1] / 2, mPos[2] + mSize[2] / 2 - winSize[2] / 2 } ) - camera = RL.CreateCamera3D() - RL.SetCamera3DPosition( camera, { 0, 8, 16 } ) - RL.SetCamera3DTarget( camera, { 0, 0, 0 } ) - RL.SetCamera3DUp( camera, { 0, 1, 0 } ) - -- RL.SetCameraMode( camera, RL.CAMERA_FREE ) + camera = Cam3D:new() + + camera:setPosition( { 0, 8, 16 } ) + camera:setTarget( { 0, 0, 0 } ) + camera:setUp( { 0, 1, 0 } ) + -- camera.mode = camera.MODES.ORBITAL + camera.mode = camera.MODES.FREE + -- camera.mode = camera.MODES.FIRST_PERSON heigthImage = RL.LoadImage( RL.GetBasePath().."../resources/images/heightmap.png" ) @@ -74,11 +84,23 @@ function RL.init() matrix = RL.MatrixMultiply( RL.MatrixIdentity(), RL.MatrixTranslate( { -4, 0, -4 } ) ) end +function RL.process( delta ) + camera:process( delta ) + + if RL.IsKeyPressed( RL.KEY_SPACE ) then + if camera.mode == camera.MODES.FREE then + camera.mode = camera.MODES.FIRST_PERSON + else + camera.mode = camera.MODES.FREE + end + end +end + function RL.draw() RL.ClearBackground( { 100, 150, 100 } ) - RL.UpdateCamera3D( camera, RL.CAMERA_FIRST_PERSON ) - RL.BeginMode3D( camera ) + camera:beginMode3D() RL.DrawMesh( mesh, material, matrix ) - RL.EndMode3D() + -- camera:draw() + camera:endMode3D() end diff --git a/examples/lightmap/main.lua b/examples/lightmap/main.lua index a85527e..991bc2d 100644 --- a/examples/lightmap/main.lua +++ b/examples/lightmap/main.lua @@ -78,7 +78,9 @@ end function RL.draw() RL.ClearBackground( { 25, 50, 50 } ) - RL.UpdateCamera3D( camera, RL.CAMERA_ORBITAL ) + -- RL.UpdateCamera3D( camera, RL.CAMERA_ORBITAL ) + -- RL.UpdateCamera3D( camera, RL.CAMERA_FREE ) + RL.UpdateCamera3D( camera, RL.CAMERA_FIRST_PERSON ) RL.BeginMode3D( camera ) RL.DrawMesh( mesh, material, matrix ) diff --git a/include/core.h b/include/core.h index e7b89bc..436bd9b 100644 --- a/include/core.h +++ b/include/core.h @@ -120,13 +120,20 @@ int lcoreGetCamera3DTarget( lua_State *L ); int lcoreGetCamera3DUp( lua_State *L ); int lcoreGetCamera3DFovy( lua_State *L ); int lcoreGetCamera3DProjection( lua_State *L ); +int lcoreGetCamera3DForward( lua_State *L ); +int lcoreGetCamera3DUpNormalized( lua_State *L ); +int lcoreGetCamera3DRight( lua_State *L ); +int lcoreCamera3DMoveForward( lua_State *L ); +int lcoreCamera3DMoveUp( lua_State *L ); +int lcoreCamera3DMoveRight( lua_State *L ); +int lcoreCamera3DMoveToTarget( lua_State *L ); +int lcoreCamera3DYaw( lua_State *L ); +int lcoreCamera3DPitch( lua_State *L ); +int lcoreCamera3DRoll( lua_State *L ); +int lcoreGetCamera3DViewMatrix( lua_State *L ); +int lcoreGetCamera3DProjectionMatrix( lua_State *L ); int lcoreUpdateCamera3D( lua_State *L ); int lcoreUpdateCamera3DPro( lua_State *L ); -// int lcoreSetCameraMode( lua_State *L ); -// int lcoreSetCameraPanControl( lua_State *L ); -// int lcoreSetCameraAltControl( lua_State *L ); -// int lcoreSetCameraSmoothZoomControl( lua_State *L ); -// int lcoreSetCameraMoveControls( lua_State *L ); /* Input-related Keyboard. */ int lcoreIsKeyPressed( lua_State *L ); int lcoreIsKeyDown( lua_State *L ); diff --git a/include/main.h b/include/main.h index 9a33572..cc12f72 100644 --- a/include/main.h +++ b/include/main.h @@ -14,6 +14,7 @@ #include "raymath.h" #include "raygui.h" #include "rlights.h" +#include "rcamera.h" #include "rlgl.h" #include "glfw3.h" #include "glfw3native.h" diff --git a/include/rcamera.h b/include/rcamera.h new file mode 100644 index 0000000..8b37ff7 --- /dev/null +++ b/include/rcamera.h @@ -0,0 +1,504 @@ +/******************************************************************************************* +* +* rcamera - Basic camera system with support for multiple camera modes +* +* CONFIGURATION: +* +* #define CAMERA_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 CAMERA_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 +#ifndef RLAPI + #define RLAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +#if defined(CAMERA_STANDALONE) + #define CAMERA_CULL_DISTANCE_NEAR 0.01 + #define CAMERA_CULL_DISTANCE_FAR 1000.0 +#else + #define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR + #define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Below types are required for CAMERA_STANDALONE usage +//---------------------------------------------------------------------------------- +#if defined(CAMERA_STANDALONE) + // Vector2, 2 components + typedef struct Vector2 { + float x; // Vector x component + float y; // Vector y component + } Vector2; + + // Vector3, 3 components + typedef struct Vector3 { + float x; // Vector x component + float y; // Vector y component + float z; // Vector z component + } Vector3; + + // Camera type, defines a camera position/orientation in 3d space + typedef struct Camera3D { + Vector3 position; // Camera position + Vector3 target; // Camera target it looks-at + Vector3 up; // Camera up vector (rotation over its axis) + float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic + int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC + } Camera3D; + + typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D + + // Camera projection + typedef enum { + CAMERA_PERSPECTIVE = 0, // Perspective projection + CAMERA_ORTHOGRAPHIC // Orthographic projection + } CameraProjection; + + // Camera system modes + typedef enum { + CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing) + CAMERA_FREE, // Camera free mode + CAMERA_ORBITAL, // Camera orbital, around target, zoom supported + CAMERA_FIRST_PERSON, // Camera first person + CAMERA_THIRD_PERSON // Camera third person + } CameraMode; +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +RLAPI Vector3 GetCameraForward(Camera *camera); +RLAPI Vector3 GetCameraUp(Camera *camera); +RLAPI Vector3 GetCameraRight(Camera *camera); + +// Camera movement +RLAPI void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane); +RLAPI void CameraMoveUp(Camera *camera, float distance); +RLAPI void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane); +RLAPI void CameraMoveToTarget(Camera *camera, float delta); + +// Camera rotation +RLAPI void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget); +RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp); +RLAPI void CameraRoll(Camera *camera, float angle); + +RLAPI Matrix GetCameraViewMatrix(Camera *camera); +RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect); + +#if defined(__cplusplus) +} +#endif + +#endif // CAMERA_H + + +/*********************************************************************************** +* +* CAMERA IMPLEMENTATION +* +************************************************************************************/ + +#if defined(CAMERA_IMPLEMENTATION) + +#include "raymath.h" // Required for vector maths: + // Vector3Add() + // Vector3Subtract() + // Vector3Scale() + // Vector3Normalize() + // Vector3Distance() + // Vector3CrossProduct() + // Vector3RotateByAxisAngle() + // Vector3Angle() + // Vector3Negate() + // MatrixLookAt() + // MatrixPerspective() + // MatrixOrtho() + // MatrixIdentity() + +// raylib required functionality: + // GetMouseDelta() + // GetMouseWheelMove() + // IsKeyDown() + // IsKeyPressed() + // GetFrameTime() + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define CAMERA_MOVE_SPEED 0.09f +#define CAMERA_ROTATION_SPEED 0.03f + +// Camera mouse movement sensitivity +#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate +#define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f + +#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second + + +#define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 8.0f +#define CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f +#define CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f + +// PLAYER (used by camera) +#define 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) +Vector3 GetCameraForward(Camera *camera) +{ + return Vector3Normalize(Vector3Subtract(camera->target, camera->position)); +} + +// Returns the cameras up vector (normalized) +// Note: The up vector might not be perpendicular to the forward vector +Vector3 GetCameraUp(Camera *camera) +{ + return Vector3Normalize(camera->up); +} + +// Returns the cameras right vector (normalized) +Vector3 GetCameraRight(Camera *camera) +{ + Vector3 forward = GetCameraForward(camera); + Vector3 up = GetCameraUp(camera); + + return Vector3CrossProduct(forward, up); +} + +// Moves the camera in its forward direction +void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane) +{ + Vector3 forward = GetCameraForward(camera); + + if (moveInWorldPlane) + { + // Project vector onto world plane + forward.y = 0; + forward = Vector3Normalize(forward); + } + + // Scale by distance + forward = Vector3Scale(forward, distance); + + // Move position and target + camera->position = Vector3Add(camera->position, forward); + camera->target = Vector3Add(camera->target, forward); +} + +// Moves the camera in its up direction +void CameraMoveUp(Camera *camera, float distance) +{ + Vector3 up = GetCameraUp(camera); + + // Scale by distance + up = Vector3Scale(up, distance); + + // Move position and target + camera->position = Vector3Add(camera->position, up); + camera->target = Vector3Add(camera->target, up); +} + +// Moves the camera target in its current right direction +void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane) +{ + Vector3 right = GetCameraRight(camera); + + if (moveInWorldPlane) + { + // Project vector onto world plane + right.y = 0; + right = Vector3Normalize(right); + } + + // Scale by distance + right = Vector3Scale(right, distance); + + // Move position and target + camera->position = Vector3Add(camera->position, right); + camera->target = Vector3Add(camera->target, right); +} + +// Moves the camera position closer/farther to/from the camera target +void CameraMoveToTarget(Camera *camera, float delta) +{ + float distance = 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 + Vector3 forward = GetCameraForward(camera); + camera->position = Vector3Add(camera->target, 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(Camera *camera, float angle, bool rotateAroundTarget) +{ + // Rotation axis + Vector3 up = GetCameraUp(camera); + + // View vector + Vector3 targetPosition = Vector3Subtract(camera->target, camera->position); + + // Rotate view vector around up axis + targetPosition = Vector3RotateByAxisAngle(targetPosition, up, angle); + + if (rotateAroundTarget) + { + // Move position relative to target + camera->position = Vector3Subtract(camera->target, targetPosition); + } + else // rotate around camera.position + { + // Move target relative to position + camera->target = 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 CAMERA_FREE) +// NOTE: angle must be provided in radians +void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp) +{ + // Up direction + Vector3 up = GetCameraUp(camera); + + // View vector + Vector3 targetPosition = Vector3Subtract(camera->target, camera->position); + + if (lockView) + { + // In these camera modes we clamp the Pitch angle + // to allow only viewing straight up or down. + + // Clamp view up + float maxAngleUp = Vector3Angle(up, targetPosition); + maxAngleUp -= 0.001f; // avoid numerical errors + if (angle > maxAngleUp) angle = maxAngleUp; + + // Clamp view down + float maxAngleDown = Vector3Angle(Vector3Negate(up), targetPosition); + maxAngleDown *= -1.0f; // downwards angle is negative + maxAngleDown += 0.001f; // avoid numerical errors + if (angle < maxAngleDown) angle = maxAngleDown; + } + + // Rotation axis + Vector3 right = GetCameraRight(camera); + + // Rotate view vector around right axis + targetPosition = Vector3RotateByAxisAngle(targetPosition, right, angle); + + if (rotateAroundTarget) + { + // Move position relative to target + camera->position = Vector3Subtract(camera->target, targetPosition); + } + else // rotate around camera.position + { + // Move target relative to position + camera->target = Vector3Add(camera->position, targetPosition); + } + + if (rotateUp) + { + // Rotate up direction around right axis + camera->up = 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(Camera *camera, float angle) +{ + // Rotation axis + Vector3 forward = GetCameraForward(camera); + + // Rotate up direction around forward axis + camera->up = Vector3RotateByAxisAngle(camera->up, forward, angle); +} + +// Returns the camera view matrix +Matrix GetCameraViewMatrix(Camera *camera) +{ + return MatrixLookAt(camera->position, camera->target, camera->up); +} + +// Returns the camera projection matrix +Matrix GetCameraProjectionMatrix(Camera *camera, float aspect) +{ + if (camera->projection == CAMERA_PERSPECTIVE) + { + return MatrixPerspective(camera->fovy*DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR); + } + else if (camera->projection == CAMERA_ORTHOGRAPHIC) + { + double top = camera->fovy/2.0; + double right = top*aspect; + + return MatrixOrtho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR); + } + + return MatrixIdentity(); +} + +#ifndef CAMERA_STANDALONE +// Update camera position for selected mode +// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM +void UpdateCamera(Camera *camera, int mode) +{ + Vector2 mousePositionDelta = GetMouseDelta(); + + bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)); + bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); + bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); + bool rotateUp = (mode == CAMERA_FREE); + + if (mode == CAMERA_ORBITAL) + { + // Orbital can just orbit + Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime()); + Vector3 view = Vector3Subtract(camera->position, camera->target); + view = Vector3Transform(view, rotation); + camera->position = Vector3Add(camera->target, view); + } + else + { + // Camera rotation + if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); + if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); + if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget); + if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget); + if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED); + if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED); + + CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); + CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); + + // Camera movement + if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); + if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); + if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); + if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); + //if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED); + //if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED); + } + + if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)) + { + // Zoom target distance + CameraMoveToTarget(camera, -GetMouseWheelMove()); + if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f); + if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f); + } +} +#endif // !CAMERA_STANDALONE + +// Update camera movement, movement/rotation values should be provided by user +void UpdateCameraPro(Camera *camera, Vector3 movement, 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; + + // Camera rotation + CameraPitch(camera, -rotation.y*DEG2RAD, lockView, rotateAroundTarget, rotateUp); + CameraYaw(camera, -rotation.x*DEG2RAD, rotateAroundTarget); + CameraRoll(camera, rotation.z*DEG2RAD); + + // Camera movement + CameraMoveForward(camera, movement.x, moveInWorldPlane); + CameraMoveRight(camera, movement.y, moveInWorldPlane); + CameraMoveUp(camera, movement.z); + + // Zoom target distance + CameraMoveToTarget(camera, zoom); +} + +#endif // CAMERA_IMPLEMENTATION @@ -3171,6 +3171,345 @@ int lcoreGetCamera3DProjection( lua_State *L ) { } /* +> forward = RL.GetCamera3DForward( camera3D camera ) + +Returns the cameras forward vector ( normalized ) + +- Failure return nil +- Success return Vector3 +*/ +int lcoreGetCamera3DForward( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.GetCamera3DForward( camera3D camera )" ); + lua_pushnil( L ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushnil( L ); + return 1; + } + uluaPushVector3( L, GetCameraForward( state->camera3Ds[ cameraId ] ) ); + + return 1; +} + +/* +> up = RL.GetCamera3DUpNormalized( camera3D camera ) + +Returns the cameras up vector ( normalized ) +Note: The up vector might not be perpendicular to the forward vector + +- Failure return nil +- Success return Vector3 +*/ +int lcoreGetCamera3DUpNormalized( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.GetCamera3DUpNormalized( camera3D camera )" ); + lua_pushnil( L ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushnil( L ); + return 1; + } + uluaPushVector3( L, GetCameraUp( state->camera3Ds[ cameraId ] ) ); + + return 1; +} + +/* +> forward = RL.GetCamera3DRight( camera3D camera ) + +Returns the cameras right vector ( normalized ) + +- Failure return nil +- Success return Vector3 +*/ +int lcoreGetCamera3DRight( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.GetCamera3DRight( camera3D camera )" ); + lua_pushnil( L ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushnil( L ); + return 1; + } + uluaPushVector3( L, GetCameraRight( state->camera3Ds[ cameraId ] ) ); + + return 1; +} + +/* +> success = RL.Camera3DMoveForward( camera3D camera, float distance, bool moveInWorldPlane ) + +Moves the camera in it's forward direction + +- Failure return false +- Success return true +*/ +int lcoreCamera3DMoveForward( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) || !lua_isboolean( L, 3 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.GetCamera3DRight( camera3D camera )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float distance = lua_tonumber( L, 2 ); + bool moveInWorldPlane = lua_toboolean( L, 3 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraMoveForward( state->camera3Ds[ cameraId ], distance, moveInWorldPlane ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> success = RL.Camera3DMoveUp( camera3D camera, float distance ) + +Moves the camera in it's up direction + +- Failure return false +- Success return true +*/ +int lcoreCamera3DMoveUp( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.Camera3DMoveUp( camera3D camera, float distance )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float distance = lua_tonumber( L, 2 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraMoveUp( state->camera3Ds[ cameraId ], distance ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> success = RL.Camera3DMoveRight( camera3D camera, float distance, bool moveInWorldPlane ) + +Moves the camera target in it's current right direction + +- Failure return false +- Success return true +*/ +int lcoreCamera3DMoveRight( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) || !lua_isboolean( L, 3 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.Camera3DMoveRight( camera3D camera, float distance, bool moveInWorldPlane )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float distance = lua_tonumber( L, 2 ); + bool moveInWorldPlane = lua_toboolean( L, 3 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraMoveRight( state->camera3Ds[ cameraId ], distance, moveInWorldPlane ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> success = RL.Camera3DMoveToTarget( camera3D camera, float delta ) + +Moves the camera position closer/farther to/from the camera target + +- Failure return false +- Success return true +*/ +int lcoreCamera3DMoveToTarget( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.Camera3DMoveToTarget( camera3D camera, float delta )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float delta = lua_tonumber( L, 2 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraMoveToTarget( state->camera3Ds[ cameraId ], delta ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> success = RL.Camera3DYaw( camera3D camera, float angle, bool rotateAroundTarget ) + +Rotates the camera around it's up vector +Yaw is "looking left and right" +If rotateAroundTarget is false, the camera rotates around it's position +Note: angle must be provided in radians + +- Failure return false +- Success return true +*/ +int lcoreCamera3DYaw( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) || !lua_isboolean( L, 3 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.Camera3DYaw( camera3D camera, float angle, bool rotateAroundTarget )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float delta = lua_tonumber( L, 2 ); + bool rotateAroundTarget = lua_toboolean( L, 3 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraYaw( state->camera3Ds[ cameraId ], delta, rotateAroundTarget ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> success = RL.Camera3DPitch( camera3D camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp ) + +Rotates the camera around it's right vector, pitch is "looking up and down" + - lockView prevents camera overrotation (aka "somersaults") + - rotateAroundTarget defines if rotation is around target or around it's position + - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) +NOTE: angle must be provided in radians + +- Failure return false +- Success return true +*/ +int lcoreCamera3DPitch( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) || !lua_isboolean( L, 3 ) + || !lua_isboolean( L, 4 ) || !lua_isboolean( L, 5 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.Camera3DYaw( camera3D camera, float angle, bool rotateAroundTarget )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float delta = lua_tonumber( L, 2 ); + bool lockView = lua_toboolean( L, 3 ); + bool rotateAroundTarget = lua_toboolean( L, 4 ); + bool rotateUp = lua_toboolean( L, 5 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraPitch( state->camera3Ds[ cameraId ], delta, lockView, rotateAroundTarget, rotateUp ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> success = RL.Camera3DRoll( camera3D camera, float angle ) + +Rotates the camera around it's forward vector +Roll is "turning your head sideways to the left or right" +Note: angle must be provided in radians + +- Failure return false +- Success return true +*/ +int lcoreCamera3DRoll( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.Camera3DRoll( camera3D camera, float angle )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float angle = lua_tonumber( L, 2 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + + CameraRoll( state->camera3Ds[ cameraId ], angle ); + lua_pushboolean( L, true ); + + return 1; +} + +/* +> view = RL.GetCamera3DViewMatrix( camera3D camera ) + +Returns the camera view matrix + +- Failure return false +- Success return Matrix +*/ +int lcoreGetCamera3DViewMatrix( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.GetCamera3DViewMatrix( camera3D camera )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + uluaPushMatrix( L, GetCameraViewMatrix( state->camera3Ds[ cameraId ] ) ); + + return 1; +} + +/* +> projection = RL.GetCamera3DProjectionMatrix( camera3D camera, float aspect ) + +Returns the camera projection matrix + +- Failure return false +- Success return Matrix +*/ +int lcoreGetCamera3DProjectionMatrix( lua_State *L ) { + if ( !lua_isnumber( L, 1 ) || !lua_isnumber( L, 2 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL.GetCamera3DProjectionMatrix( camera3D camera, float aspect )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t cameraId = lua_tointeger( L, 1 ); + float aspect = lua_tonumber( L, 2 ); + + if ( !validCamera3D( cameraId ) ) { + lua_pushboolean( L, false ); + return 1; + } + uluaPushMatrix( L, GetCameraProjectionMatrix( state->camera3Ds[ cameraId ], aspect ) ); + + return 1; +} + +/* > success = RL.UpdateCamera3D( camera3D camera, int mode ) Update camera position for selected mode diff --git a/src/lua_core.c b/src/lua_core.c index ea0851b..dae916e 100644 --- a/src/lua_core.c +++ b/src/lua_core.c @@ -814,13 +814,20 @@ void luaRegister() { assingGlobalFunction( "GetCamera3DUp", lcoreGetCamera3DUp ); assingGlobalFunction( "GetCamera3DFovy", lcoreGetCamera3DFovy ); assingGlobalFunction( "GetCamera3DProjection", lcoreGetCamera3DProjection ); + assingGlobalFunction( "GetCamera3DForward", lcoreGetCamera3DForward ); + assingGlobalFunction( "GetCamera3DUpNormalized", lcoreGetCamera3DUpNormalized ); + assingGlobalFunction( "GetCamera3DRight", lcoreGetCamera3DRight ); + assingGlobalFunction( "Camera3DMoveForward", lcoreCamera3DMoveForward ); + assingGlobalFunction( "Camera3DMoveUp", lcoreCamera3DMoveUp ); + assingGlobalFunction( "Camera3DMoveRight", lcoreCamera3DMoveRight ); + assingGlobalFunction( "Camera3DMoveToTarget", lcoreCamera3DMoveToTarget ); + assingGlobalFunction( "Camera3DYaw", lcoreCamera3DYaw ); + assingGlobalFunction( "Camera3DPitch", lcoreCamera3DPitch ); + assingGlobalFunction( "Camera3DRoll", lcoreCamera3DRoll ); + assingGlobalFunction( "GetCamera3DViewMatrix", lcoreGetCamera3DViewMatrix ); + assingGlobalFunction( "GetCamera3DProjectionMatrix", lcoreGetCamera3DProjectionMatrix ); assingGlobalFunction( "UpdateCamera3D", lcoreUpdateCamera3D ); assingGlobalFunction( "UpdateCamera3DPro", lcoreUpdateCamera3DPro ); - // assingGlobalFunction( "SetCameraMode", lcoreSetCameraMode ); - // assingGlobalFunction( "SetCameraPanControl", lcoreSetCameraPanControl ); - // assingGlobalFunction( "SetCameraAltControl", lcoreSetCameraAltControl ); - // assingGlobalFunction( "SetCameraSmoothZoomControl", lcoreSetCameraSmoothZoomControl ); - // assingGlobalFunction( "SetCameraMoveControls", lcoreSetCameraMoveControls ); /* Input-related Keyboard. */ assingGlobalFunction( "IsKeyPressed", lcoreIsKeyPressed ); assingGlobalFunction( "IsKeyDown", lcoreIsKeyDown ); |
