Cogs.Core
CameraUtils.h
1#pragma once
2
3#include "CameraHelper.h"
4#include "Math/Projection.h"
5#include "Components/Core/TransformComponent.h"
6#include <type_traits>
7
8
21{
22 namespace detail
23 {
24 template<class TransformComponent>
25 inline auto getRotation(const TransformComponent transformComponent)
26 {
27 using TransformType = std::remove_cv_t<std::remove_pointer_t<TransformComponent>>;
28 if constexpr (std::is_same_v<TransformType, Cogs::Core::TransformComponent>) {
29 return transformComponent->transform.trs.rotation;
30 }
31 else {
32 return glm::quat(transformComponent->rotation);
33 }
34 }
35
36 template<class TransformComponent>
37 inline void setPosition(const TransformComponent transformComponent, const glm::vec3& position)
38 {
39 using TransformType = std::remove_cv_t<std::remove_pointer_t<TransformComponent>>;
40 if constexpr (std::is_same_v<TransformType, Cogs::Core::TransformComponent>) {
41 transformComponent->transform.trs.position = position;
42 }
43 else {
44 transformComponent->position = position;
45 }
46 }
47 }
48
57 template<class TransformComponent, class OrbitingCameraController>
58 inline glm::quat getCameraOrientation(const TransformComponent transformComponent, const OrbitingCameraController orbitingCameraController)
59 {
60 glm::quat orientation;
61 if (orbitingCameraController) {
62 orientation = Cogs::Utility::CameraHelper::getOrientation(orbitingCameraController->horizontalAngle, orbitingCameraController->verticalAngle);
63 }
64 else {
65 orientation = detail::getRotation(transformComponent);
66 }
67
68 return orientation;
69 }
70
84 template<class CameraComponent, class TransformComponent, class OrbitingCameraController, typename ProjectionMode>
85 inline glm::dvec3 viewAll(const CameraComponent cameraComponent, const TransformComponent transformComponent, const OrbitingCameraController orbitingCameraController, const ProjectionMode projectionMode, const Cogs::Geometry::DBoundingBox& boundingBox, glm::vec2 viewport = glm::vec2(0.0f, 0.0f))
86 {
87 float fieldOfView = cameraComponent->fieldOfView;
88 glm::quat orientation = Cogs::Utility::CameraUtils::getCameraOrientation(transformComponent, orbitingCameraController);
89 glm::dvec3 position = Cogs::Utility::CameraHelper::getViewAllPosition(boundingBox, orientation, fieldOfView, viewport);
90 float focalDistance = Cogs::Utility::CameraHelper::getFocalDistance(position, boundingBox);
91 if (orbitingCameraController) {
92 const glm::dvec3 center = Cogs::Utility::CameraHelper::getCenter(boundingBox);
93 orbitingCameraController->cameraTarget = center;
94 orbitingCameraController->distance = focalDistance;
95 orbitingCameraController->setChanged();
96 }
97 else {
98 transformComponent->coordinates = position;
99 detail::setPosition(transformComponent, glm::vec3(0, 0, 0));
100 transformComponent->setChanged();
101 }
102
103 const float farDistance = Cogs::Utility::CameraHelper::getFarDistance(position, boundingBox);
104 const float oldFarDistance = cameraComponent->farDistance;
105 if (oldFarDistance < farDistance) {
106 cameraComponent->farDistance = farDistance;
107 }
108
109 cameraComponent->focalDistance = focalDistance;
110
111 if (projectionMode == ProjectionMode::Orthographic) {
112 cameraComponent->orthoHeight = Cogs::Utility::CameraHelper::getOrthoHeight(boundingBox);
113 }
114
115 cameraComponent->setChanged();
116
117 return position;
118 }
119
131 template<class CameraData>
132 inline bool getProjectedCoordinates(const glm::vec2& coordinatesToProject, const CameraData& cameraData, const glm::vec3& targetPlaneNormal, const glm::vec3& targetPlanePosition, glm::vec3& projectedCoordinates)
133 {
134 glm::vec3 planeNormal = targetPlaneNormal;
135 if (planeNormal.x == 0.f && planeNormal.y == 0.f && planeNormal.z == 0.f) {
136 planeNormal = -glm::vec3(cameraData.inverseViewMatrix[2]);
137 }
138
139 const glm::vec3 cameraPosition = glm::vec3(cameraData.inverseViewMatrix[3]);
140 glm::mat4 invViewProj = glm::inverse(cameraData.rawProjectionMatrix * cameraData.viewMatrix);
141 float nx = ((2.0f * (static_cast<float>(coordinatesToProject.x) / cameraData.viewportSize.x)) - 1.0f);
142 float ny = -((2.0f * (static_cast<float>(coordinatesToProject.y) / cameraData.viewportSize.y)) - 1.0f);
143 glm::vec4 nearPlaneHit = invViewProj * glm::vec4(nx, ny, -1.f, 1.f);
144 glm::vec3 rayOrigin = (1.f / nearPlaneHit.w)*glm::vec3(nearPlaneHit);
145 glm::vec4 farPlaneHit = invViewProj * glm::vec4(nx, ny, 1.f, 1.f);
146
147 if (farPlaneHit.w == 0) {
148 farPlaneHit.w = glm::epsilon<float>();
149 }
150 glm::vec3 rayDirection = glm::normalize((1.f / farPlaneHit.w)*glm::vec3(farPlaneHit) - rayOrigin);
151 float t;
152 bool intersects = Cogs::Geometry::projectToPlane(rayOrigin, rayDirection, targetPlanePosition, planeNormal, projectedCoordinates, &t);
153 bool isInFrontOfCamera = t + glm::distance(cameraPosition, rayOrigin) >= 0;
154
155 return intersects && isInFrontOfCamera;
156 }
157}
COGSCORE_DLL_API float getOrthoHeight(const Cogs::Geometry::DBoundingBox &boundingBox)
Calculate Orthographic camera orthoHeight Field to view boundingbox.
COGSCORE_DLL_API glm::dvec3 getViewAllPosition(const Cogs::Geometry::DBoundingBox &boundingBox, const glm::quat &orientation, float fieldOfView, glm::vec2 viewport)
COGSCORE_DLL_API glm::dvec3 getCenter(const Cogs::Geometry::DBoundingBox &boundingBox)
Gets center of non-empty bounding box.
COGSCORE_DLL_API float getFocalDistance(const glm::dvec3 &position, const Cogs::Geometry::DBoundingBox &boundingBox)
Gets distance from given position (camera position) to center of bounding box.
COGSCORE_DLL_API float getFarDistance(const glm::dvec3 &position, const Cogs::Geometry::DBoundingBox &boundingBox)
Gets camera far distance given bounding box.
COGSCORE_DLL_API glm::quat getOrientation(float horizontalAngle, float verticalAngle)
Gets the camera orientation from the horizontal and vertical angle values.
Contains common operations for camera setup.
Definition: CameraUtils.h:21
bool getProjectedCoordinates(const glm::vec2 &coordinatesToProject, const CameraData &cameraData, const glm::vec3 &targetPlaneNormal, const glm::vec3 &targetPlanePosition, glm::vec3 &projectedCoordinates)
Project a screen coordinate onto a plane in 3d space.
Definition: CameraUtils.h:132
glm::dvec3 viewAll(const CameraComponent cameraComponent, const TransformComponent transformComponent, const OrbitingCameraController orbitingCameraController, const ProjectionMode projectionMode, const Cogs::Geometry::DBoundingBox &boundingBox, glm::vec2 viewport=glm::vec2(0.0f, 0.0f))
View all for given bounding box.
Definition: CameraUtils.h:85
glm::quat getCameraOrientation(const TransformComponent transformComponent, const OrbitingCameraController orbitingCameraController)
Definition: CameraUtils.h:58