#include <../math/vector.h> #include <../math/point.h> #include <../math/quaternion.h> #include <../math/matrix.h> #include #ifndef STIM_CAMERA_H #define STIM_CAMERA_H namespace stim{ class camera { vector d; //direction that the camera is pointing point p; //position of the camera vector up; //"up" direction float focus; //focal length of the camera float fov; //private function makes sure that the up vector is orthogonal to the direction vector and both are normalized void stabalize() { vector side = up.cross(d); up = d.cross(side); up = up.norm(); d = d.norm(); } public: void setPosition(point pos) { p = pos; } void setPosition(float x, float y, float z){setPosition(point(x, y, z));} void setFocalDistance(float distance){focus = distance;} void setFOV(float field_of_view){fov = field_of_view;} void LookAt(point pos) { //find the new direction d = pos - p; //find the distance from the look-at point to the current position focus = d.len(); //stabalize the camera stabalize(); } void LookAt(float px, float py, float pz){LookAt(point(px, py, pz));} void LookAt(point pos, vector new_up){up = new_up; LookAt(pos);} void LookAt(float px, float py, float pz, float ux, float uy, float uz){LookAt(point(px, py, pz), vector(ux, uy, uz));} void LookAtDolly(float lx, float ly, float lz) { //find the current focus point point f = p + focus*d; vector T = point(lx, ly, lz) - f; p = p + T; } void Dolly(vector direction) { p = p+direction; } void Dolly(float x, float y, float z){Dolly(vector(x, y, z));} void Push(float delta) { if(delta > focus) delta = focus; focus -= delta; Dolly(d*delta); } void Pan(float theta_x, float theta_y, float theta_z) { //x rotation is around the up axis quaternion qx; qx.CreateRotation(theta_x, up[0], up[1], up[2]); //y rotation is around the side axis vector side = up.cross(d); quaternion qy; qy.CreateRotation(theta_y, side[0], side[1], side[2]); //z rotation is around the direction vector quaternion qz; qz.CreateRotation(theta_z, d[0], d[1], d[2]); //combine the rotations in x, y, z order quaternion final = qz*qy*qx; //get the rotation matrix matrix rot_matrix = final.toMatrix3(); //apply the rotation d = rot_matrix*d; up = rot_matrix*up; //stabalize the camera stabalize(); } void Pan(float theta_x){Pan(theta_x, 0, 0);} void Tilt(float theta_y){Pan(0, theta_y, 0);} void Twist(float theta_z){Pan(0, 0, theta_z);} void Zoom(float delta) { fov -= delta; if(fov < 0.5) fov = 0.5; if(fov > 180) fov = 180; } void OrbitFocus(float theta_x, float theta_y) { //find the focal point point focal_point = p + focus*d; //center the coordinate system on the focal point point centered = p - (focal_point - point(0, 0, 0)); //create the x rotation (around the up vector) quaternion qx; qx.CreateRotation(theta_x, up[0], up[1], up[2]); centered = point(0, 0, 0) + qx.toMatrix3()*(centered - point(0, 0, 0)); //get a side vector for theta_y rotation vector side = up.cross((point(0, 0, 0) - centered).norm()); quaternion qy; qy.CreateRotation(theta_y, side[0], side[1], side[2]); centered = point(0, 0, 0) + qy.toMatrix3()*(centered - point(0, 0, 0)); //perform the rotation on the centered camera position //centered = final.toMatrix()*centered; //re-position the camera p = centered + (focal_point - point(0, 0, 0)); //make sure we are looking at the focal point LookAt(focal_point); //stabalize the camera stabalize(); } void Slide(float u, float v) { vector V = up.norm(); vector U = up.cross(d).norm(); p = p + (V * v) + (U * u); } //accessor methods point getPosition(){return p;} vector getUp(){return up;} vector getDirection(){return d;} point getLookAt(){return p + focus*d;} float getFOV(){return fov;} //output the camera settings const void print(std::ostream& output) { output<<"Position: "<(0, 0, 0); d = vector(0, 0, 1); up = vector(0, 1, 0); focus = 1; } }; } #endif