#include #include #include #include #include #ifndef STIM_CAMERA_H #define STIM_CAMERA_H namespace stim{ class camera { vec3 d; //direction that the camera is pointing vec3 p; //position of the camera vec3 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() { vec3 side = up.cross(d); up = d.cross(side); up = up.norm(); d = d.norm(); } public: void setPosition(vec3 pos) { p = pos; } void setPosition(float x, float y, float z){setPosition(vec3(x, y, z));} void setFocalDistance(float distance){focus = distance;} void setFOV(float field_of_view){fov = field_of_view;} void LookAt(vec3 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(vec3(px, py, pz));} void LookAt(vec3 pos, vec3 new_up){up = new_up; LookAt(pos);} void LookAt(float px, float py, float pz, float ux, float uy, float uz){LookAt(vec3(px, py, pz), vec3(ux, uy, uz));} void LookAtDolly(float lx, float ly, float lz) { //find the current focus point vec3 f = p + focus*d; vec3 T = vec3(lx, ly, lz) - f; p = p + T; } void Dolly(vec3 direction) { p = p+direction; } void Dolly(float x, float y, float z){Dolly(vec3(x, y, z));} /// Push the camera along the view direction 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 vec3 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_sq 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 vec3 focal_point = p + focus*d; //center the coordinate system on the focal point vec3 centered = p - (focal_point - vec3(0, 0, 0)); //create the x rotation (around the up vector) quaternion qx; qx.CreateRotation(theta_x, up[0], up[1], up[2]); centered = vec3(0, 0, 0) + qx.toMatrix3()*(centered - vec3(0, 0, 0)); //get a side vector for theta_y rotation vec3 side = up.cross((vec3(0, 0, 0) - centered).norm()); quaternion qy; qy.CreateRotation(theta_y, side[0], side[1], side[2]); centered = vec3(0, 0, 0) + qy.toMatrix3()*(centered - vec3(0, 0, 0)); //perform the rotation on the centered camera position //centered = final.toMatrix()*centered; //re-position the camera p = centered + (focal_point - vec3(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) { vec3 V = up.norm(); vec3 U = up.cross(d).norm(); p = p + (V * v) + (U * u); } //accessor methods vec3 getPosition(){return p;} vec3 getUp(){return up;} vec3 getDirection(){return d;} vec3 getLookAt(){return p + focus*d;} float getFOV(){return fov;} //output the camera settings void print(std::ostream& output) { output<<"Position: "<(0, 0, 0); d = vec3(0, 0, 1); up = vec3(0, 1, 0); focus = 1; fov = 60; } /// Outputs the camera information as a string std::string str(){ std::stringstream ss; ss<"<<(p + d * focus).str(); return ss.str(); } }; } #endif