colobot/colobot-base/graphics/engine/camera.h

418 lines
13 KiB
C
Raw Normal View History

/*
* This file is part of the Colobot: Gold Edition source code
2023-08-06 21:15:48 +00:00
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
2015-08-22 14:40:02 +00:00
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
/**
* \file graphics/engine/camera.h
2012-09-19 21:50:28 +00:00
* \brief Camera handling - CCamera class
*/
#pragma once
#include "graphics/core/color.h"
2012-06-25 14:37:03 +00:00
class CObject;
class CRobotMain;
class CInput;
struct Event;
2012-09-19 21:50:28 +00:00
// Graphics module namespace
2015-08-02 09:40:47 +00:00
namespace Gfx
{
class CEngine;
class CTerrain;
class CWater;
enum class TransparencyMode : unsigned char;
2012-06-25 14:37:03 +00:00
/**
\enum CameraType
\brief Type of camera */
2022-02-26 18:44:49 +00:00
enum CameraType : unsigned char
2012-06-25 14:37:03 +00:00
{
//! Undefined
2016-05-28 16:52:30 +00:00
CAM_TYPE_NULL = 0,
2016-05-28 16:42:48 +00:00
//! Free camera
2016-05-28 16:52:30 +00:00
CAM_TYPE_FREE,
//! Camera while editing a program
2016-05-28 16:52:30 +00:00
CAM_TYPE_EDIT,
//! Camera on board a robot
2016-05-28 16:52:30 +00:00
CAM_TYPE_ONBOARD,
//! Camera behind a robot
2016-05-28 16:52:30 +00:00
CAM_TYPE_BACK,
//! Static camera following robot
2016-05-28 16:52:30 +00:00
CAM_TYPE_FIX,
//! Camera steady after explosion
2016-05-28 16:52:30 +00:00
CAM_TYPE_EXPLO,
2016-05-28 16:42:48 +00:00
//! Camera during a cutscene
2016-05-28 16:52:30 +00:00
CAM_TYPE_SCRIPT,
2016-05-28 16:42:48 +00:00
//! Visit camera, rotates around given position
2016-05-28 16:52:30 +00:00
CAM_TYPE_VISIT,
//! Static camera height
2016-05-28 16:52:30 +00:00
CAM_TYPE_PLANE,
2012-06-25 14:37:03 +00:00
};
enum CameraSmooth
{
//! Sharp
CAM_SMOOTH_NONE = 0,
//! Normal
CAM_SMOOTH_NORM = 1,
//! Hard
CAM_SMOOTH_HARD = 2,
2012-06-25 14:37:03 +00:00
};
enum CenteringPhase
{
CAM_PHASE_NULL = 0,
CAM_PHASE_START = 1,
CAM_PHASE_WAIT = 2,
CAM_PHASE_STOP = 3,
2012-06-25 14:37:03 +00:00
};
enum CameraEffect
{
//! No effect
CAM_EFFECT_NULL = 0,
//! Digging in
CAM_EFFECT_TERRAFORM = 1,
2016-05-28 16:42:48 +00:00
//! Hard landing
CAM_EFFECT_CRASH = 2,
//! Explosion
CAM_EFFECT_EXPLO = 3,
2016-05-28 16:42:48 +00:00
//! Shot by an enemy
CAM_EFFECT_SHOT = 4,
//! Vibration during construction
CAM_EFFECT_VIBRATION = 5,
2016-05-28 16:42:48 +00:00
//! Overheated reactor
CAM_EFFECT_PET = 6,
2012-06-25 14:37:03 +00:00
};
enum CameraOverEffect
2012-06-25 14:37:03 +00:00
{
//! No effect
CAM_OVER_EFFECT_NULL = 0,
//! Flash red
CAM_OVER_EFFECT_BLOOD = 1,
//! White -> nothing
CAM_OVER_EFFECT_FADEIN_WHITE = 2,
//! Nothing -> white
CAM_OVER_EFFECT_FADEOUT_WHITE = 3,
//! Nothing -> blue
CAM_OVER_EFFECT_FADEOUT_BLACK = 4,
//! Lightning
CAM_OVER_EFFECT_LIGHTNING = 5,
2012-06-25 14:37:03 +00:00
};
/**
\class CCamera
\brief Camera moving in 3D scene
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
This class manages everything related to animating the camera in 3D scene.
Calculated values are then passed to Gfx::CEngine.
*/
2015-08-02 09:40:47 +00:00
class CCamera
{
public:
CCamera();
~CCamera();
2012-06-25 14:37:03 +00:00
//! Management of an event
bool EventProcess(const Event &event);
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
/**
* \brief Initializes the camera
* \param eye Initial eye position
* \param lookat Initial lookat position
* \param delay Time of the initial entry animation
*/
void Init(glm::vec3 eye, glm::vec3 lookat, float delay);
2012-06-25 14:37:03 +00:00
//! Sets the object controlling the camera
2012-09-17 18:47:27 +00:00
void SetControllingObject(CObject* object);
2016-05-28 16:42:48 +00:00
//! Gets the object controlling the camera
2012-09-17 18:47:27 +00:00
CObject* GetControllingObject();
2012-06-25 14:37:03 +00:00
//! Change the type of camera
void SetType(CameraType type);
2016-05-28 16:42:48 +00:00
//! Get the type of the camera
CameraType GetType();
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
//! Set smoothing mode
void SetSmooth(CameraSmooth type);
2016-05-28 16:42:48 +00:00
//! Get smoothing mode
2016-01-30 09:37:39 +00:00
CameraSmooth GetSmooth();
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
//! Returns the current point of view of the camera
void GetCamera(glm::vec3 &eye, glm::vec3 &lookat);
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
//! \name Visit camera management (CAM_TYPE_VISIT) - camera in this mode shows a position, constantly rotating around it
//@{
//! Start visit camera
void StartVisit(glm::vec3 goal, float dist);
2016-05-28 16:42:48 +00:00
//! Stop visit camera
void StopVisit();
2016-05-28 16:42:48 +00:00
//@}
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
//! \name Camera "centering" - moves the camera to show some happening action (e.g. sniffer sniffing)
//@{
//! Move camera to show happening action
bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
2016-05-28 16:42:48 +00:00
//! Go back to normal position after showing some happening action
bool StopCentering(CObject *object, float time);
2016-05-28 16:42:48 +00:00
//! Abort centering animation in the current position
void AbortCentering();
2016-05-28 16:42:48 +00:00
//@}
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
//! \name Camera shake effects
//@{
//! Starts a camera shake effect
void StartEffect(CameraEffect effect, glm::vec3 pos, float force);
2016-05-28 16:42:48 +00:00
//! Removes the camera shake effect
void FlushEffect();
//@}
2012-06-25 14:37:03 +00:00
2016-05-28 16:42:48 +00:00
//! \name Camera overlay effects
//@{
//! Starts camera overlay effect
void StartOver(CameraOverEffect effect, glm::vec3 pos, float force);
2016-05-28 16:42:48 +00:00
//! Removes camera overlay effect
void FlushOver();
2016-05-28 16:42:48 +00:00
//! Specifies camera overlay effect base color
2012-09-19 21:50:28 +00:00
void SetOverBaseColor(Color color);
2016-05-28 16:42:48 +00:00
//@}
//! \name Script camera - cutscenes controlled by external code
//@{
//! Script camera: Set camera position
void SetScriptCamera(glm::vec3 eye, glm::vec3 lookat);
2016-05-28 16:42:48 +00:00
//! Script camera: Animate to given camera position
void SetScriptCameraAnimate(glm::vec3 eye, glm::vec3 lookat);
2016-05-28 16:42:48 +00:00
//! Script camera: Animate to given eye position
void SetScriptCameraAnimateEye(glm::vec3 eye);
2016-05-28 16:42:48 +00:00
//! Script camera: Animate to given lookat position
void SetScriptCameraAnimateLookat(glm::vec3 lookat);
2016-05-28 16:42:48 +00:00
//@}
//! \name Configuration settings
//@{
void SetEffect(bool enable);
bool GetEffect();
2014-10-22 04:44:17 +00:00
void SetBlood(bool enable);
bool GetBlood();
void SetOldCameraScroll(bool scroll);
bool GetOldCameraScroll();
void SetCameraInvertX(bool invert);
bool GetCameraInvertX();
void SetCameraInvertY(bool invert);
bool GetCameraInvertY();
2016-05-28 16:42:48 +00:00
//@}
2012-06-25 14:37:03 +00:00
2016-05-28 10:50:32 +00:00
//! Temporarily freeze camera movement
void SetFreeze(bool freeze);
2016-05-28 16:42:48 +00:00
//! Set camera speed
void SetCameraSpeed(float speed);
2012-06-25 14:37:03 +00:00
protected:
2016-05-28 16:42:48 +00:00
//! Advances the effect of the camera
void EffectFrame(const Event &event);
//! Advanced overlay effect in the foreground
void OverFrame(const Event &event);
bool EventFrameFree(const Event &event, bool keysAllowed);
bool EventFrameBack(const Event &event);
bool EventFrameFix(const Event &event);
bool EventFrameExplo(const Event &event);
bool EventFrameOnBoard(const Event &event);
bool EventFrameVisit(const Event &event);
bool EventFrameScript(const Event &event);
2016-05-28 16:42:48 +00:00
/**
* \brief Calculates camera animation and sends updated camera position to the 3D engine
* \param eyePt Eye point
* \param lookatPt Lookat point
* \param rTime Time since last time this function was called (used to calculate animation)
* \see SetViewParams
*/
void UpdateCameraAnimation(const glm::vec3 &eyePt, const glm::vec3 &lookatPt, float rTime);
2016-05-28 16:42:48 +00:00
/**
* \brief Avoid the obstacles
*
* For CAM_TYPE_BACK: make obstacles transparent
* For CAM_TYPE_FIX or CAM_TYPE_PLANE: adjust eye not to hit the obstacles
*
* \param eye Eye position, may be adjusted
* \param lookat Lookat point
*/
void IsCollision(glm::vec3 &eye, glm::vec3 lookat);
2016-05-28 16:42:48 +00:00
//! Avoid the obstacles (CAM_TYPE_BACK)
void IsCollisionBack();
//! Avoid the obstacles (CAM_TYPE_FIX or CAM_TYPE_PLANE)
void IsCollisionFix(glm::vec3 &eye, glm::vec3 lookat);
//! Adjusts the camera not to enter the ground
glm::vec3 ExcludeTerrain(glm::vec3 eye, glm::vec3 lookat, float &angleH, float &angleV);
//! Adjusts the camera not to enter an object
glm::vec3 ExcludeObject(glm::vec3 eye, glm::vec3 lookat, float &angleH, float &angleV);
2016-05-28 16:42:48 +00:00
/**
* \brief Updates the location and direction of the camera in the 3D engine
* \param eye Eye point
* \param lookat Lookat point
* \param up Up vector
* \see CEngine::SetViewParams
*/
void SetViewParams(const glm::vec3 &eye, const glm::vec3 &lookat, const glm::vec3 &up = glm::vec3(0.0f, 1.0f, 0.0f));
2012-06-25 14:37:03 +00:00
/**
* \brief Calculate camera movement (from user inputs) to apply
* \return glm::vec3 where x, y represent respectively horizontal and vertical angle change in radians and z represents zoom (distance change)
* \remarks Should not be called more often than once every EVENT_FRAME
**/
glm::vec3 CalculateCameraMovement(const Event &event, bool keysAllowed = true);
2012-06-25 14:37:03 +00:00
protected:
2012-09-19 21:50:28 +00:00
CEngine* m_engine;
CRobotMain* m_main;
2012-09-19 21:50:28 +00:00
CTerrain* m_terrain;
CWater* m_water;
CInput* m_input;
//! The type of camera
2012-09-19 21:50:28 +00:00
CameraType m_type;
//! Type of smoothing
2012-09-19 21:50:28 +00:00
CameraSmooth m_smooth;
//! Object linked to the camera
2016-05-28 16:42:48 +00:00
CObject* m_cameraObj;
2016-05-28 16:42:48 +00:00
//! Remaining time of initial camera entry animation
float m_initDelay;
//! Current eye
glm::vec3 m_actualEye{ 0, 0, 0 };
//! Current aim
glm::vec3 m_actualLookat{ 0, 0, 0 };
//! Final eye
glm::vec3 m_finalEye{ 0, 0, 0 };
//! Final lookat
glm::vec3 m_finalLookat{ 0, 0, 0 };
//! Eye position at the moment of entering CAM_TYPE_INFO/CAM_TYPE_VISIT
glm::vec3 m_prevEye{ 0, 0, 0 };
//! Lookat position at the moment of entering CAM_TYPE_INFO/CAM_TYPE_VISIT
glm::vec3 m_prevLookat{ 0, 0, 0 };
2016-05-28 16:42:48 +00:00
float m_focus;
//! CAM_TYPE_FREE: eye
glm::vec3 m_eyePt{ 0, 0, 0 };
//! CAM_TYPE_FREE: horizontal direction
float m_directionH;
//! CAM_TYPE_FREE: vertical direction
float m_directionV;
//! CAM_TYPE_FREE: height above the ground
float m_heightEye;
//! CAM_TYPE_FREE: height above the ground
float m_heightLookat;
//! CAM_TYPE_FREE: speed of movement
float m_speed;
//! CAM_TYPE_BACK: distance
float m_backDist;
2016-05-28 16:42:48 +00:00
//! CAM_TYPE_BACK: minimal distance
float m_backMin;
2016-05-28 16:42:48 +00:00
//! CAM_TYPE_BACK: additional horizontal direction
float m_addDirectionH;
2016-05-28 16:42:48 +00:00
//! CAM_TYPE_BACK: additional vertical direction
float m_addDirectionV;
//! CAM_TYPE_FIX: distance
float m_fixDist;
2016-05-28 16:42:48 +00:00
//! CAM_TYPE_FIX: horizontal direction
float m_fixDirectionH;
2016-05-28 16:42:48 +00:00
//! CAM_TYPE_FIX: vertical direction
float m_fixDirectionV;
//! CAM_TYPE_VISIT: target position
glm::vec3 m_visitGoal{ 0, 0, 0 };
//! CAM_TYPE_VISIT: distance
float m_visitDist;
//! CAM_TYPE_VISIT: relative time
float m_visitTime;
//! CAM_TYPE_VISIT: initial type
2012-09-19 21:50:28 +00:00
CameraType m_visitType;
//! CAM_TYPE_VISIT: direction
float m_visitDirectionV;
//! Last known mouse position, used to calculate change since last frame
glm::vec2 m_mousePos = { 0.5f, 0.5f };
2016-05-28 16:42:48 +00:00
//! Change of mouse position since last frame
glm::vec2 m_mouseDelta = { 0.0f, 0.0f };
2016-05-28 16:42:48 +00:00
//! Change of camera position caused by edge camera
glm::vec2 m_mouseDeltaEdge = { 0.0f, 0.0f };
2016-05-28 16:42:48 +00:00
//! Change of mouse wheel since last frame
float m_mouseWheelDelta = 0.0f;
2012-09-19 21:50:28 +00:00
CenteringPhase m_centeringPhase;
float m_centeringAngleH;
float m_centeringAngleV;
float m_centeringDist;
float m_centeringCurrentH;
float m_centeringCurrentV;
float m_centeringTime;
float m_centeringProgress;
2012-09-19 21:50:28 +00:00
CameraEffect m_effectType;
glm::vec3 m_effectPos{ 0, 0, 0 };
float m_effectForce;
float m_effectProgress;
glm::vec3 m_effectOffset{ 0, 0, 0 };
2012-09-19 21:50:28 +00:00
CameraOverEffect m_overType;
float m_overForce;
float m_overTime;
2012-09-19 21:50:28 +00:00
Color m_overColorBase;
Color m_overColor;
TransparencyMode m_overMode;
float m_overFadeIn;
float m_overFadeOut;
glm::vec3 m_scriptEye{ 0, 0, 0 };
glm::vec3 m_scriptLookat{ 0, 0, 0 };
2016-05-28 16:42:48 +00:00
//! Is camera frozen?
bool m_freeze = false;
//! \name Configuration settings
//@{
bool m_effect;
2014-10-22 04:44:17 +00:00
bool m_blood;
2016-05-28 16:42:48 +00:00
bool m_oldCameraScroll;
bool m_cameraInvertX;
bool m_cameraInvertY;
2016-05-28 16:42:48 +00:00
//@}
2012-06-25 14:37:03 +00:00
};
2012-09-19 21:50:28 +00:00
} // namespace Gfx