summaryrefslogtreecommitdiff
path: root/wave-sim/src/graphics/camera.cpp
diff options
context:
space:
mode:
authorSebastian Park <SebPark03@gmail.com>2024-04-10 02:45:04 -0400
committerSebastian Park <SebPark03@gmail.com>2024-04-10 02:45:04 -0400
commit47cd8a592ecad52c1b01f27d23476c0a5afeb7f1 (patch)
tree36b9abaff4e92a4a6df0d5ecb0e43e05c3aefd48 /wave-sim/src/graphics/camera.cpp
parentfd19124693bb32835ad97802ba1950cd5202dbd2 (diff)
initial
Diffstat (limited to 'wave-sim/src/graphics/camera.cpp')
-rw-r--r--wave-sim/src/graphics/camera.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/wave-sim/src/graphics/camera.cpp b/wave-sim/src/graphics/camera.cpp
new file mode 100644
index 0000000..85fc7d9
--- /dev/null
+++ b/wave-sim/src/graphics/camera.cpp
@@ -0,0 +1,188 @@
+#include "graphics/camera.h"
+
+#include <iostream>
+
+Camera::Camera()
+ : m_position(0,0,0),
+ m_pitch(0), m_yaw(0),
+ m_look(0, 0, 1),
+ m_orbitPoint(0, 0, 0),
+ m_isOrbiting(false),
+ m_view(Eigen::Matrix4f::Identity()),
+ m_proj(Eigen::Matrix4f::Identity()),
+ m_viewDirty(true),
+ m_projDirty(true),
+ m_fovY(90), m_aspect(1), m_near(0.1f), m_far(50.f),
+ m_zoom(1)
+{}
+
+// ================== Position
+
+void Camera::setPosition(const Eigen::Vector3f &position)
+{
+ m_position = position;
+ m_viewDirty = true;
+}
+
+void Camera::move(const Eigen::Vector3f &deltaPosition)
+{
+ if (deltaPosition.squaredNorm() == 0) return;
+
+ m_position += deltaPosition;
+
+ if (m_isOrbiting) {
+ m_orbitPoint += deltaPosition;
+ }
+
+ m_viewDirty = true;
+
+}
+
+// ================== Rotation
+
+void Camera::setRotation(float pitch, float yaw)
+{
+ m_pitch = pitch;
+ m_yaw = yaw;
+ m_viewDirty = true;
+ updateLook();
+}
+
+void Camera::rotate(float deltaPitch, float deltaYaw)
+{
+ m_pitch += deltaPitch;
+ m_yaw += deltaYaw;
+ m_pitch = std::clamp(m_pitch, (float) -M_PI_2 + 0.01f, (float) M_PI_2 - 0.01f);
+ m_viewDirty = true;
+ updateLook();
+
+ if (m_isOrbiting) {
+ m_position = m_orbitPoint - m_look * m_zoom;
+ }
+}
+
+// ================== Position and Rotation
+
+void Camera::lookAt(const Eigen::Vector3f &eye, const Eigen::Vector3f &target)
+{
+ m_position = eye;
+ m_look = (target - eye).normalized();
+ m_viewDirty = true;
+ updatePitchAndYaw();
+}
+
+// ================== Orbiting
+
+void Camera::setOrbitPoint(const Eigen::Vector3f &orbitPoint)
+{
+ m_orbitPoint = orbitPoint;
+ m_viewDirty = true;
+}
+
+bool Camera::getIsOrbiting()
+{
+ return m_isOrbiting;
+}
+
+void Camera::setIsOrbiting(bool isOrbiting)
+{
+ m_isOrbiting = isOrbiting;
+ m_viewDirty = true;
+}
+
+void Camera::toggleIsOrbiting()
+{
+ m_isOrbiting = !m_isOrbiting;
+ m_viewDirty = true;
+
+ if (m_isOrbiting) {
+ m_zoom = (m_orbitPoint - m_position).norm();
+ m_look = (m_orbitPoint - m_position).normalized();
+ updatePitchAndYaw();
+ }
+}
+
+void Camera::zoom(float zoomMultiplier)
+{
+ if (!m_isOrbiting) return;
+
+ m_zoom *= zoomMultiplier;
+ m_position = m_orbitPoint - m_look * m_zoom;
+ m_viewDirty = true;
+}
+
+// ================== Intrinsics
+
+void Camera::setPerspective(float fovY, float aspect, float near, float far)
+{
+ m_fovY = fovY;
+ m_aspect = aspect;
+ m_near = near;
+ m_far = far;
+ m_projDirty = true;
+}
+
+void Camera::setAspect(float aspect)
+{
+ m_aspect = aspect;
+ m_projDirty = true;
+}
+
+// ================== Important Getters
+
+const Eigen::Matrix4f &Camera::getView()
+{
+ if (m_viewDirty) {
+ Eigen::Matrix3f R;
+ Eigen::Vector3f f = m_look.normalized();
+ Eigen::Vector3f u = Eigen::Vector3f::UnitY();
+ Eigen::Vector3f s = f.cross(u).normalized();
+ u = s.cross(f);
+ R.col(0) = s;
+ R.col(1) = u;
+ R.col(2) = -f;
+ m_view.topLeftCorner<3, 3>() = R.transpose();
+ m_view.topRightCorner<3, 1>() = -R.transpose() * m_position;
+ m_view(3, 3) = 1.f;
+ m_viewDirty = false;
+ }
+ return m_view;
+}
+
+const Eigen::Matrix4f &Camera::getProjection()
+{
+ if(m_projDirty) {
+ float theta = m_fovY * 0.5f;
+ float invRange = 1.f / (m_far - m_near);
+ float invtan = 1.f / tanf(theta);
+ m_proj(0, 0) = invtan / m_aspect;
+ m_proj(1, 1) = invtan;
+ m_proj(2, 2) = -(m_near + m_far) * invRange;
+ m_proj(3, 2) = -1;
+ m_proj(2, 3) = -2 * m_near * m_far * invRange;
+ m_proj(3, 3) = 0;
+ m_projDirty = false;
+ }
+ return m_proj;
+}
+
+const Eigen::Vector3f &Camera::getLook()
+{
+ return m_look;
+}
+
+// ================== Private Helpers
+
+void Camera::updateLook()
+{
+ m_look = Eigen::Vector3f(0, 0, 1);
+ m_look = Eigen::AngleAxis<float>(m_pitch, Eigen::Vector3f::UnitX()) * m_look;
+ m_look = Eigen::AngleAxis<float>(m_yaw, Eigen::Vector3f::UnitY()) * m_look;
+ m_look = m_look.normalized();
+}
+
+void Camera::updatePitchAndYaw()
+{
+ m_pitch = asinf(-m_look.y());
+ m_yaw = atan2f(m_look.x(), m_look.z());
+}