Repository navigation
Expand file tree
/
Copy pathArcballCam.hpp
More file actions
150 lines (129 loc) · 5.56 KB
/
Copy pathArcballCam.hpp
File metadata and controls
150 lines (129 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
* @file ArcballCam.hpp
* @brief Concrete Arcball Camera implementation with Perspective Projection
* @author Dr. Jeffrey Paone
*
* @copyright MIT License Copyright (c) 2021 Dr. Jeffrey Paone
*
* These functions, classes, and constants help minimize common
* code that needs to be written.
*/
#ifndef CSCI441_ARCBALL_CAM_HPP
#define CSCI441_ARCBALL_CAM_HPP
#include "PerspectiveCamera.hpp"
namespace CSCI441 {
/**
* @brief A camera that implements an ArcBall camera model.
* @note camera direction is controlled by setting theta & phi and rotating the camera
*/
class ArcballCam final : public CSCI441::PerspectiveCamera {
public:
/**
* @brief initializes the Arcball Camera and sets the minimum/maximum radius the camera can zoom through as well as the perspective projection
* @param minRadius minimum radius (zoom) for camera - defaults to 2.0 world space units
* @param maxRadius maximum radius (zoom) for camera - defaults to 30.0 world space units
* @param aspectRatio aspect ratio of view plane (defaults to 1.0f)
* @param fovy vertical field of view (defaults to pi/4 radians)
* @param nearClipPlane near z clip plane (defaults to 0.001f)
* @param farClipPlane far z clip plane (defaults to 1000.0f)
* @note field of view specified in radians
*/
explicit ArcballCam(GLfloat minRadius = 2.0f, GLfloat maxRadius = 30.0f, GLfloat aspectRatio = 1.0f, GLfloat fovy = glm::quarter_pi<GLfloat>(), GLfloat nearClipPlane = 0.001f, GLfloat farClipPlane = 1000.0f);
/**
* @brief construct a copy an existing camera
*/
ArcballCam(const ArcballCam&) = default;
/**
* @brief assign a copy of an existing camera
* @return our newly assigned camera
*/
ArcballCam& operator=(const ArcballCam&) = default;
/**
* @brief construct a camera by moving ane existing camera object
*/
ArcballCam(ArcballCam&&) = default;
/**
* @brief reassign an existing camera to ourselves
* @return our newly assigned camera
*/
ArcballCam& operator=(ArcballCam&&) = default;
/**
* @brief properly destroy concrete children
*/
~ArcballCam() override = default;
/**
* @brief converts spherical theta & phi to cartesian x,y,z direction vector
* @note sets the camera's position to be on a sphere centered at the camera's
* look at position
* @note internally sets the camera's view matrix
*/
void recomputeOrientation() override;
/**
* @brief updates the camera's position by decreasing the camera's radius
* @param movementFactor distance factor to scale the movement step
* @note internally sets the camera's view matrix
*/
void moveForward(GLfloat movementFactor) override;
/**
* @brief updates the camera's position by increasing the camera's radius
* @param movementFactor distance factor to scale the movement step
* @note internally sets the camera's view matrix
*/
void moveBackward(GLfloat movementFactor) override;
private:
/**
* @brief updates the camera position and recalculates the view matrix
*/
void _updateArcballCameraViewMatrix();
/**
* @brief keeps the current camera radius within the range (_minRadius, _maxRadius)
*/
void _clampRadius();
/**
* @brief minimum allowable radius of camera
*/
GLfloat _minRadius;
/**
* @brief maximum allowable radius of camera
*/
GLfloat _maxRadius;
};
}
inline CSCI441::ArcballCam::ArcballCam(
const GLfloat minRadius,
const GLfloat maxRadius,
const GLfloat aspectRatio,
const GLfloat fovy,
const GLfloat nearClipPlane,
const GLfloat farClipPlane
) : CSCI441::PerspectiveCamera(aspectRatio, fovy, nearClipPlane, farClipPlane),
_minRadius(minRadius),
_maxRadius(maxRadius)
{
recomputeOrientation();
}
inline void CSCI441::ArcballCam::recomputeOrientation() {
// compute direction vector based on spherical to cartesian conversion
mCameraDirection.x = glm::sin(mCameraTheta ) * glm::sin(mCameraPhi ) * mCameraRadius;
mCameraDirection.y = -glm::cos(mCameraPhi ) * mCameraRadius;
mCameraDirection.z = -glm::cos(mCameraTheta ) * glm::sin(mCameraPhi ) * mCameraRadius;
_updateArcballCameraViewMatrix();
}
inline void CSCI441::ArcballCam::moveForward(const GLfloat movementFactor) {
mCameraRadius -= movementFactor; // camera "moves forward" by reducing the radius to get closer to the look at point
_clampRadius(); // ensure camera doesn't get too close
recomputeOrientation(); // update view matrix
}
inline void CSCI441::ArcballCam::moveBackward(const GLfloat movementFactor) {
mCameraRadius += movementFactor; // camera "moves backward" by increasing the radius to get further away from the look at point
_clampRadius(); // ensure camera doesn't get too far away
recomputeOrientation(); // update view matrix
}
inline void CSCI441::ArcballCam::_updateArcballCameraViewMatrix() {
setPosition(mCameraLookAtPoint + mCameraDirection );
computeViewMatrix();
}
inline void CSCI441::ArcballCam::_clampRadius() {
mCameraRadius = glm::clamp(mCameraRadius, _minRadius, _maxRadius);
}
#endif // CSCI441_ARCBALL_CAM_HPP