#pragma once // GLM #include #include #include // DGL #include "DGL_Types.hpp" // Non-Standard C++ #include "Cpp_Alias.hpp" namespace DGL { // Function sfn Cosine(gFloat _angleInRadians) { return glm::cos(_angleInRadians); } sfn Sine(gFloat _angleInRadians) { return glm::sin(_angleInRadians); } template sfn CreateLookAtView(ro Ref(Generic::Vector3) _viewPosition, ro Ref(Generic::Vector3) _lookAtPosition, ro Ref(Generic::Vector3) _upDirection) -> Matrix4x4 { return glm::lookAt(_viewPosition, _lookAtPosition, _upDirection); } sfn CreateOrthographic(gFloat _leftScreenCoord, gFloat _rightScreenCoord, gFloat _bottomScreenCoord, gFloat _topScreenCoord, gFloat _nearPlane, gFloat _farPlane) { return glm::ortho(_leftScreenCoord, _rightScreenCoord, _bottomScreenCoord, _topScreenCoord, _nearPlane, _farPlane); } template sfn CreatePerspective(FloatType _fieldOfView, FloatType _aspectRatio, FloatType _nearPlane, FloatType _farPlane) { return glm::perspective(_fieldOfView, _aspectRatio, _nearPlane, _farPlane); } sfn GetCrossNormal(ro Ref(Vector3) _subj, ro Ref(Vector3) _ref) -> Vector3 { return glm::cross(_subj, _ref); } sfn GetDirection(ro Ref(Vector3) _vectorSpecified) { return glm::normalize(_vectorSpecified); } sfn Inverse(ro Ref(Matrix4x4) _matrix) { return glm::inverse(_matrix); } sfn Rotate(ro Ref(Matrix4x4) _matrix, gFloat _rotationAngleAmount, ro Ref(Vector3) _axis) -> Matrix4x4 { return glm::rotate(_matrix, _rotationAngleAmount, _axis); } sfn Scale(ro Ref(Matrix4x4) _matrix, ro Ref(Vector3) _scaleBy) { return glm::scale(_matrix, _scaleBy); } template sfn ToRadians(Type _degrees) -> Type { return glm::radians(_degrees); } sfn Translate(ro Ref(Matrix4x4) _matrix, ro Ref(Vector3) _translationAmount) { return glm::translate(_matrix, _translationAmount); } struct ClippingPlanes { gFloat Near, Far; ClippingPlanes(gFloat _near, gFloat _far) : Near(_near), Far(_far) {}; }; namespace DefaultSpace { gFloat AspectRatio = 16.0f / 10.0f, FieldOfView = 90.0f , NearClippingPlane = 0.01f , FarClippingPlane = 1000.0f ; Vector3 CameraPosition( 0, 0, 2), LookAtPosition( 0, 0, 0), RightDirection( 1, 0, 0), UpDirection ( 0, 1, 0), FrontDirection( 0, 0, 1) ; gInt ScreenWidth = 1280, ScreenHeight = 800, ScreenCenterWidth = ScreenWidth / 2, ScreenCenterHeight = ScreenHeight / 2; } struct Camera { gFloat AspectRatio, FieldOfView, Yaw, Pitch, Roll; ClippingPlanes ClipSpace; CoordSpace Viewport; Projection Orthographic, Perspective; Vector3 Position, LookAtPosition, UpDirection, FrontDirection, RightDirection; Camera ( gFloat _aspectRatio , gFloat _fieldOfView , ro Ref(ClippingPlanes) _clippingPlanes, ro Ref(Vector3 ) _position , ro Ref(Vector3 ) _lookAtPosition, ro Ref(Vector3 ) _upDirection , ro Ref(Vector3 ) _frontDirection ) : AspectRatio (_aspectRatio ), FieldOfView (_fieldOfView ), ClipSpace (_clippingPlanes), Position (_position ), LookAtPosition(_lookAtPosition), UpDirection (_upDirection ), FrontDirection(_frontDirection) { Yaw = -90.0f; Pitch = 0.0f; Roll = 0.0f; UpdateCamera(); Orthographic = CreateOrthographic(0.0f, gFloat(DefaultSpace::ScreenWidth), 0.0f, gFloat(DefaultSpace::ScreenHeight), ClipSpace.Near, ClipSpace.Far); Perspective = CreatePerspective(ToRadians(FieldOfView), AspectRatio, ClipSpace.Near, ClipSpace.Far); } sfn Move(EDirection _direction, gFloat _translationAmount, gFloat _deltaTime) { switch (_direction) { case EDirection::Up: { Position -= UpDirection * _translationAmount * _deltaTime; break; } case EDirection::Down: { Position += UpDirection * _translationAmount * _deltaTime; break; } case EDirection::Left: { Position -= GetDirection(GetCrossNormal(FrontDirection, UpDirection)) * _translationAmount * _deltaTime; break; } case EDirection::Right: { Position += GetDirection(GetCrossNormal(FrontDirection, UpDirection)) * _translationAmount * _deltaTime; break; } case EDirection::Forward: { Position += FrontDirection * _translationAmount * _deltaTime; break; } case EDirection::Backward: { Position -= FrontDirection * _translationAmount * _deltaTime; break; } default: { throw std::logic_error("Direction move not defined."); } } return; } sfn Move(ro Ref(Vector3) _translationAmount, gFloat _deltaTime) { Position += _translationAmount * _deltaTime; return; } sfn Rotate(ERotationAxis _pivot, gFloat _rotationAmount, gFloat _deltaTime) { switch (_pivot) { case ERotationAxis::Pitch: { Pitch -= _rotationAmount * _deltaTime; if (Pitch > 89.9f) { Pitch = 89.9f; } else if (Pitch < -89.9f) { Pitch = -89.9f; } return; } case ERotationAxis::Roll: { Roll += _rotationAmount * _deltaTime; return; } case ERotationAxis::Yaw: { Yaw += _rotationAmount * _deltaTime; return; } } } sfn UpdateCamera() -> void { FrontDirection.x = Cosine(ToRadians(Yaw )) * Cosine(ToRadians(Pitch)); FrontDirection.y = Sine (ToRadians(Pitch)) ; FrontDirection.z = Sine (ToRadians(Yaw )) * Cosine(ToRadians(Pitch)); FrontDirection = GetDirection(FrontDirection ); RightDirection = GetDirection(GetCrossNormal(FrontDirection, DefaultSpace::UpDirection )); UpDirection = GetDirection(GetCrossNormal(RightDirection, FrontDirection)); LookAtPosition = Position + FrontDirection; Viewport = CreateLookAtView(Position, LookAtPosition, UpDirection); return; } }; namespace DefaultSpace { Camera WorldCamera ( AspectRatio , FieldOfView , ClippingPlanes(NearClippingPlane, FarClippingPlane), CameraPosition , LookAtPosition , UpDirection , FrontDirection ); CoordSpace WorldSpace(Matrix4x4(1.0f)); CoordSpace Screenspace = WorldCamera.Perspective * WorldCamera.Viewport * WorldSpace; sfn UpdateScreenspace() { Screenspace = WorldCamera.Perspective * WorldCamera.Viewport * WorldSpace; return; } } }