// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "../Actor.h"
#include "Engine/Core/Math/BoundingFrustum.h"
#include "Engine/Core/Math/Viewport.h"
#include "Engine/Core/Math/Ray.h"
#include "Engine/Core/Types/LayersMask.h"
#include "Engine/Graphics/Enums.h"
#include "Engine/Scripting/ScriptingObjectReference.h"
#if USE_EDITOR
#include "Engine/Content/AssetReference.h"
#include "Engine/Graphics/Models/ModelInstanceEntry.h"
#include "Engine/Content/Assets/Model.h"
#endif
///
/// Describes the camera projection and view. Provides information about how to render scene (viewport location and direction, etc.).
///
API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\"), ActorToolbox(\"Visuals\")")
class FLAXENGINE_API Camera : public Actor
{
DECLARE_SCENE_OBJECT(Camera);
// List with all created cameras actors on the scene
static Array Cameras;
// The current cut-scene camera. Set by the Scene Animation Player to the current shot camera.
static Camera* CutSceneCamera;
// The overriden main camera.
API_FIELD() static ScriptingObjectReference OverrideMainCamera;
// Gets the main camera.
API_PROPERTY() static Camera* GetMainCamera();
private:
BoundingFrustum _frustum;
// Camera Settings
bool _usePerspective;
float _fov;
float _customAspectRatio;
float _near;
float _far;
float _orthoSize;
float _orthoScale;
#if USE_EDITOR
AssetReference _previewModel;
ModelInstanceEntries _previewModelBuffer;
BoundingBox _previewModelBox;
int32 _sceneRenderingKey = -1;
#endif
public:
///
/// Gets the frustum.
///
API_PROPERTY() FORCE_INLINE BoundingFrustum GetFrustum() const
{
return _frustum;
}
public:
///
/// Gets the value indicating if camera should use perspective rendering mode, otherwise it will use orthographic projection.
///
API_PROPERTY(Attributes="EditorOrder(10), DefaultValue(true), EditorDisplay(\"Camera\")")
bool GetUsePerspective() const;
///
/// Sets the value indicating if camera should use perspective rendering mode, otherwise it will use orthographic projection.
///
API_PROPERTY() void SetUsePerspective(bool value);
///
/// Gets the camera's field of view (in degrees).
///
API_PROPERTY(Attributes="EditorOrder(20), DefaultValue(60.0f), Limit(0, 179), EditorDisplay(\"Camera\", \"Field Of View\"), VisibleIf(nameof(UsePerspective)), ValueCategory(Utils.ValueCategory.Angle)")
float GetFieldOfView() const;
///
/// Sets camera's field of view (in degrees).
///
API_PROPERTY() void SetFieldOfView(float value);
///
/// Gets the custom aspect ratio. 0 if not use custom value.
///
API_PROPERTY(Attributes="EditorOrder(50), DefaultValue(0.0f), Limit(0, 10, 0.01f), EditorDisplay(\"Camera\")")
float GetCustomAspectRatio() const;
///
/// Sets the custom aspect ratio. 0 if not use custom value.
///
API_PROPERTY() void SetCustomAspectRatio(float value);
///
/// Gets camera's near plane distance.
///
API_PROPERTY(Attributes="EditorOrder(30), DefaultValue(10.0f), Limit(0, 1000, 0.05f), EditorDisplay(\"Camera\"), ValueCategory(Utils.ValueCategory.Distance)")
float GetNearPlane() const;
///
/// Sets camera's near plane distance.
///
API_PROPERTY() void SetNearPlane(float value);
///
/// Gets camera's far plane distance.
///
API_PROPERTY(Attributes="EditorOrder(40), DefaultValue(40000.0f), Limit(0, float.MaxValue, 5), EditorDisplay(\"Camera\"), ValueCategory(Utils.ValueCategory.Distance)")
float GetFarPlane() const;
///
/// Sets camera's far plane distance.
///
API_PROPERTY() void SetFarPlane(float value);
///
/// Gets the orthographic projection view height (width is based on the aspect ratio). Use `0` for size to be based on the viewport size.
///
API_PROPERTY(Attributes="EditorOrder(59), DefaultValue(0.0f), Limit(0.0f), EditorDisplay(\"Camera\"), VisibleIf(nameof(UsePerspective), true)")
float GetOrthographicSize() const;
///
/// Sets the orthographic projection view height (width is based on the aspect ratio). Use `0` for size to be based on the viewport size.
///
API_PROPERTY() void SetOrthographicSize(float value);
///
/// Gets the orthographic projection scale.
///
API_PROPERTY(Attributes="EditorOrder(60), DefaultValue(1.0f), Limit(0.0001f, 1000, 0.01f), EditorDisplay(\"Camera\"), VisibleIf(nameof(UsePerspective), true)")
float GetOrthographicScale() const;
///
/// Sets the orthographic projection scale.
///
API_PROPERTY() void SetOrthographicScale(float value);
///
/// The layers mask used for rendering using this camera. Can be used to include or exclude specific actor layers from the drawing.
///
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Camera\")")
LayersMask RenderLayersMask;
///
/// Frame rendering flags used to switch between graphics features for this camera.
///
API_FIELD(Attributes = "EditorOrder(110), EditorDisplay(\"Camera\")")
ViewFlags RenderFlags = ViewFlags::DefaultGame;
///
/// Describes frame rendering modes for this camera.
///
API_FIELD(Attributes = "EditorOrder(120), EditorDisplay(\"Camera\")")
ViewMode RenderMode = ViewMode::Default;
public:
///
/// Projects the point from 3D world-space to game window coordinates (in screen pixels for default viewport calculated from ).
///
/// The input world-space location (XYZ in world).
/// The output game window coordinates (XY in screen pixels).
API_FUNCTION() void ProjectPoint(const Vector3& worldSpaceLocation, API_PARAM(Out) Float2& gameWindowSpaceLocation) const;
///
/// Projects the point from 3D world-space to the camera viewport-space (in screen pixels for given viewport).
///
/// The input world-space location (XYZ in world).
/// The output camera viewport-space location (XY in screen pixels).
/// The viewport.
API_FUNCTION() void ProjectPoint(const Vector3& worldSpaceLocation, API_PARAM(Out) Float2& cameraViewportSpaceLocation, API_PARAM(Ref) const Viewport& viewport) const;
///
/// Converts a game window-space point into a corresponding point in world space.
///
/// The input game window coordinates (XY in screen pixels).
/// The input camera-relative depth position (eg. clipping plane).
/// The output world-space location (XYZ in world).
API_FUNCTION() void UnprojectPoint(const Float2& gameWindowSpaceLocation, float depth, API_PARAM(Out) Vector3& worldSpaceLocation) const;
///
/// Converts a camera viewport-space point into a corresponding point in world space.
///
/// The input camera viewport-space location (XY in screen pixels).
/// The input camera-relative depth position (eg. clipping plane).
/// The output world-space location (XYZ in world).
/// The viewport.
API_FUNCTION() void UnprojectPoint(const Float2& cameraViewportSpaceLocation, float depth, API_PARAM(Out) Vector3& worldSpaceLocation, API_PARAM(Ref) const Viewport& viewport) const;
///
/// Checks if the 3d point of the world is in the camera's field of view.
///
/// World Position (XYZ).
/// Returns true if the point is within the field of view.
API_FUNCTION() bool IsPointOnView(const Vector3& worldSpaceLocation) const;
///
/// Converts the mouse position to 3D ray.
///
/// The mouse position.
/// Mouse ray
API_FUNCTION() Ray ConvertMouseToRay(const Float2& mousePosition) const;
///
/// Converts the mouse position to 3D ray.
///
/// The mouse position.
/// The viewport.
/// Mouse ray
API_FUNCTION() Ray ConvertMouseToRay(const Float2& mousePosition, API_PARAM(Ref) const Viewport& viewport) const;
///
/// Gets the camera viewport.
///
API_PROPERTY() Viewport GetViewport() const;
///
/// Calculates the view and the projection matrices for the camera.
///
/// The result camera view matrix.
/// The result camera projection matrix.
API_FUNCTION() void GetMatrices(API_PARAM(Out) Matrix& view, API_PARAM(Out) Matrix& projection) const;
///
/// Calculates the view and the projection matrices for the camera. Support using custom viewport.
///
/// The result camera view matrix.
/// The result camera projection matrix.
/// The custom output viewport.
API_FUNCTION() void GetMatrices(API_PARAM(Out) Matrix& view, API_PARAM(Out) Matrix& projection, API_PARAM(Ref) const Viewport& viewport) const;
///
/// Calculates the view and the projection matrices for the camera. Support using custom viewport and view origin.
///
/// The result camera view matrix.
/// The result camera projection matrix.
/// The custom output viewport.
/// The rendering view origin (for relative-to-camera rendering).
API_FUNCTION() void GetMatrices(API_PARAM(Out) Matrix& view, API_PARAM(Out) Matrix& projection, API_PARAM(Ref) const Viewport& viewport, API_PARAM(Ref) const Vector3& origin) const;
#if USE_EDITOR
// Intersection check for editor picking the camera
API_FUNCTION() bool IntersectsItselfEditor(API_PARAM(Ref) const Ray& ray, API_PARAM(Out) Real& distance);
#endif
private:
#if USE_EDITOR
void OnPreviewModelLoaded();
#endif
void UpdateCache();
public:
// [Actor]
#if USE_EDITOR
BoundingBox GetEditorBox() const override;
bool HasContentLoaded() const override;
void Draw(RenderContext& renderContext) override;
void OnDebugDrawSelected() override;
#endif
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
protected:
// [Actor]
void OnEnable() override;
void OnDisable() override;
void OnTransformChanged() override;
#if USE_EDITOR
void BeginPlay(SceneBeginData* data) override;
#endif
};