summaryrefslogtreecommitdiff
path: root/hw6/src/camera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'hw6/src/camera.cpp')
-rw-r--r--hw6/src/camera.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/hw6/src/camera.cpp b/hw6/src/camera.cpp
new file mode 100644
index 0000000..3393dc9
--- /dev/null
+++ b/hw6/src/camera.cpp
@@ -0,0 +1,150 @@
+/******************************************************************/
+/* This file is part of the homework assignments for CSCI-427/527 */
+/* at The College of William & Mary and authored by Pieter Peers. */
+/* No part of this file, whether altered or in original form, can */
+/* be distributed or used outside the context of CSCI-427/527 */
+/* without consent of either the College of William & Mary or */
+/* Pieter Peers. */
+/******************************************************************/
+
+#include <cmath>
+
+#include "constants.h"
+#include "camera.h"
+
+/////////////////
+// Constructor //
+/////////////////
+camera::camera(void)
+{
+ _eye = vec3d();
+ _view = vec3d(0.0f, 0.0f, -1.0f);
+ _up = vec3d(0.0f, 1.0f, 0.0f);
+ _fov = 60.0f;
+ _width = _height = 256;
+}
+
+
+camera::camera(const vec3d& eye, const vec3d& viewDirection, const vec3d& up, float fov, size_t xres, size_t yres)
+{
+ _eye = eye;
+ _view = normalize(viewDirection);
+ _up = normalize(up);
+ _fov = fov;
+ _width = xres;
+ _height = yres;
+
+ // fix up if needed
+ vec3d right = _view.cross(up).normalize();
+ _up = right.cross(_view).normalize();
+}
+
+
+camera::camera(const camera& cam)
+{
+ _eye = cam._eye;
+ _view = cam._view;
+ _up = cam._up;
+ _fov = cam._fov;
+ _width = cam._width;
+ _height = cam._height;
+}
+
+
+///////////////
+// Operators //
+///////////////
+camera& camera::operator=(const camera& cam)
+{
+ _assign(cam);
+ return *this;
+}
+
+
+ray camera::operator()(float x, float y) const
+{
+ vec3d right = _view.cross(_up).normalize();
+
+ // aspect ratio
+ float aspect = (float)(_height) / (float)(_width);
+ float tanFov = tan(_fov / 180.0f * PI);
+
+ // compute view plane center, and U and V unnormalized axes.
+ vec3d center = _eye + _view;
+ vec3d U = 2.0f * tanFov * right;
+ vec3d V = -2.0f * tanFov * aspect * _up; // y runs from top to bottom (opposite direction of up)
+
+ // get point on view plane
+ vec3d p = center + (x / (float)(_width) - 0.5f) * U + (y / (float)(_height) - 0.5f) * V;
+
+ // Done.
+ return ray(_eye, p - _eye);
+}
+
+
+//////////////
+// Mutators //
+//////////////
+void camera::frameBoundingBox(const boundingBox& bb)
+{
+ // determine the best eye location, given the other parameters and a bounding box such that the bounding box maximally occupies the view
+ vec3d right = _view.cross(_up).normalize();
+ _eye = 0.5f * (bb.corner(true,true,true) + bb.corner(false,false,false));
+
+ // => find max projection in up and right direction.
+ float maxRight=-LARGE, maxUp=-LARGE, maxDepth=-LARGE;
+ for(unsigned int i=0; i < 8; i++)
+ {
+ vec3d c = bb.corner( (i&1)==1, (i&2)==2, (i&4)==4 ) - _eye;
+
+ float r = fabs(c.dot(right));
+ float u = fabs(c.dot(_up));
+ float d = fabs(c.dot(_view));
+
+ maxRight = std::max(maxRight, r);
+ maxUp = std::max(maxUp, u);
+ maxDepth = std::max(maxDepth, d);
+ }
+
+ // => compute optimal distance for up and right
+ float aspect = (float)(_height) / (float)(_width);
+ float tanFov = tan(_fov / 180.0f * PI);
+ float optDistUp = fabs(maxUp / tanFov);
+ float optDistRight = fabs(maxRight / (tanFov * aspect));
+
+ // => move _eye back based on (max) optimal distance
+ _eye -= _view * (std::max(optDistUp, optDistRight) + maxDepth);
+}
+
+
+/////////////////////
+// Private Methods //
+/////////////////////
+void camera::_swap(camera& cam)
+{
+ // sanity check
+ if(&cam == this) return;
+
+ // swap
+ swap(_eye, cam._eye);
+ swap(_view, cam._view);
+ swap(_up, cam._up);
+ std::swap(_fov, cam._fov);
+ std::swap(_width, cam._width);
+ std::swap(_height, cam._height);
+}
+
+
+void camera::_assign(const camera& cam)
+{
+ // sanity check
+ if(&cam == this) return;
+
+ // copy
+ _eye = cam._eye;
+ _view = cam._view;
+ _up = cam._up;
+ _fov = cam._fov;
+ _width = cam._width;
+ _height = cam._height;
+}