Waterflow
Visualize water in terrain
src/camera.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #include "camera.h"
00009 #include "gtc/type_ptr.hpp"
00010 #include "gtx/rotate_vector.hpp"
00011 #include <cmath>
00012 #include <iostream>
00013 
00014 // ===== Constructor =====
00015 
00016 Camera::Camera(glm::vec3 startPos, int* initScreenW, int* initScreenH, int tH, int tW, int xzL, int yLL, int yLH, DataHandler* terr)
00017 {
00018     unlocked = false; 
00019     position = startPos;
00020     fi = 0.0f;
00021     theta = (GLfloat)M_PI / 2.0f;
00022     
00023     up = glm::vec3(0,1,0);
00024 
00025     screenW = initScreenW;
00026     screenH = initScreenH;
00027 
00028     terrH = tH;
00029     terrW = tW;
00030     xzLim = xzL;
00031     yLimLo = yLL;
00032     yLimHi = yLH;
00033     terrain = terr;
00034 
00035     rotSpeed = 0.01f;
00036     speed = 1.0f;
00037     drawDistance = 10000.0f;
00038 
00039     isFrozen = false;
00040 
00041     changeLookAtPos(0,0);
00042     updateVTP();
00043 }
00044 
00045 // ===== Methods =====
00046 
00047 bool Camera::isInCollisionBox(glm::vec3 transVec, bool xz)
00048 {
00049     if (unlocked) {
00050         return true;
00051     }
00052     glm::vec3 testVec = glm::vec3(glm::translate(glm::mat4(1.0f), transVec) * glm::vec4(position, 1));
00053     bool okToMove = true;
00054     if (xz)
00055     {
00056         // Check x.
00057         okToMove = okToMove && testVec.x > -xzLim && testVec.x < terrH + xzLim;
00058         // Check z.
00059         okToMove = okToMove && testVec.z > -xzLim && testVec.z < terrW + xzLim;
00060     }
00061     else
00062     {
00063         // Check y.
00064         okToMove = okToMove && testVec.y >= terrain->giveHeight(testVec.x, testVec.z) + yLimLo && testVec.y < terrain->getTerrainScale() + yLimHi;
00065     }
00066     return okToMove;
00067 }
00068 
00069 void Camera::unlock(){
00070     unlocked = true;
00071 }
00072 
00073 void Camera::rotate(char direction, GLfloat angle)
00074 {
00075     switch (direction){
00076     case 'x':
00077         lookAtPos = glm::rotate(lookAtPos, angle, glm::vec3(1, 0, 0));
00078         break;
00079     case 'y':
00080         lookAtPos = glm::rotate(lookAtPos, angle, glm::vec3(0, 1, 0));
00081         break;
00082     case 'z':
00083         lookAtPos = glm::rotate(lookAtPos, angle, glm::vec3(0, 0, 1));
00084         break;
00085     }
00086 
00087     updateWTV();
00088 }
00089 
00090 void Camera::translate(GLfloat dx, GLfloat dy, GLfloat dz)
00091 {
00092     if (!isFrozen) {
00093         glm::vec3 testVec = glm::vec3(dx, dy, dz);
00094         if (!isInCollisionBox(glm::vec3(0, dy, 0), false))
00095         {
00096             if (dy > 0)
00097             {
00098                 testVec.y = 0;
00099             }
00100             else
00101             {
00102                 testVec.y = terrain->giveHeight(position.x, position.z) + yLimLo - position.y;
00103             }
00104         }
00105         if (!isInCollisionBox(glm::vec3(dx, 0, 0), true))
00106         {
00107             testVec.x = 0;
00108         }
00109         if (!isInCollisionBox(glm::vec3(0, 0, dz), true))
00110         {
00111             testVec.z = 0;
00112         }
00113         position = glm::vec3(glm::translate(glm::mat4(1.0f), testVec) * glm::vec4(position, 1));
00114         lookAtPos = glm::vec3(glm::translate(glm::mat4(1.0f), testVec) * glm::vec4(lookAtPos, 1));
00115         updateWTV();
00116     }
00117 }
00118 
00119 void Camera::forward(GLfloat d)
00120 {
00121     glm::vec3 forward_vec = lookAtPos - position;
00122     forward_vec = speed * d * forward_vec;
00123     translate(forward_vec.x, forward_vec.y, forward_vec.z);
00124 }
00125 
00126 void Camera::strafe(GLfloat d)
00127 {
00128     glm::vec3 strafe_vec = lookAtPos - position;
00129     strafe_vec = glm::cross(up, strafe_vec);
00130     strafe_vec = glm::normalize(strafe_vec);
00131     strafe_vec = speed * d * strafe_vec;
00132     translate(strafe_vec.x, strafe_vec.y, strafe_vec.z);
00133 }
00134 
00135 void Camera::jump(GLfloat d) {
00136     glm::vec3 temp_vec = lookAtPos - position;
00137     glm::vec3 jump_vec = glm::cross(up, temp_vec);
00138     jump_vec = glm::cross(temp_vec, jump_vec);
00139     jump_vec = glm::normalize(jump_vec);
00140     jump_vec = speed * d * jump_vec;
00141     translate(jump_vec.x, jump_vec.y, jump_vec.z);
00142 }
00143 
00144 void Camera::updateWTV()
00145 {
00146     WTVMatrix = glm::lookAt(position, lookAtPos, up);
00147 }
00148 
00149 void Camera::updateVTP() {
00150     float ratio = (GLfloat)(*screenW) / (GLfloat)(*screenH);
00151     VTPMatrix = glm::perspective((GLfloat)M_PI / 2, ratio, 1.0f, drawDistance);
00152 }
00153 
00154 void Camera::uploadCamData(GLuint program)
00155 {
00156     glUseProgram(program);
00157     glUniformMatrix4fv(glGetUniformLocation(program, "VTPMatrix"), 1, GL_FALSE, glm::value_ptr(VTPMatrix));
00158     glUniformMatrix4fv(glGetUniformLocation(program, "WTVMatrix"), 1, GL_FALSE, glm::value_ptr(WTVMatrix));
00159     glUniform3fv(glGetUniformLocation(program, "camPos"), 1, glm::value_ptr(position));
00160 }
00161 
00162 void Camera::toggleFrozen() {
00163     isFrozen = !isFrozen;
00164 }
00165 
00166 void Camera::changeLookAtPos(int xrel, int yrel)
00167 {
00168     if (!isFrozen) {
00169         float eps = 0.001f;
00170 
00171         fi += rotSpeed * xrel;
00172         theta += rotSpeed * yrel;
00173         
00174         fi = fmod(fi, 2.0f * (GLfloat)M_PI);
00175         theta = theta < (GLfloat)M_PI - eps ? (theta > eps ? theta : eps) : (GLfloat)M_PI - eps;
00176 
00177         lookAtPos.x = -sin(theta)*sin(fi) + position.x;
00178         lookAtPos.y = cos(theta) + position.y;
00179         lookAtPos.z = sin(theta)*cos(fi) + position.z;
00180 
00181         updateWTV();
00182     }
00183 }
00184 
00185 // ===== Getters =====
00186 
00187 glm::mat4* Camera::getWTV() {
00188     return &WTVMatrix;
00189 }
00190 glm::mat4* Camera::getVTP() {
00191     return &VTPMatrix;
00192 }
00193 glm::vec3* Camera::getPos() {
00194     return &position;
00195 }
00196 GLfloat Camera::getSpeed() {
00197     return speed;
00198 }
00199 GLfloat* Camera::getSpeedPtr() {
00200     return &speed;
00201 }
00202 GLfloat Camera::getRotSpeed() {
00203     return rotSpeed;
00204 }
00205 GLfloat* Camera::getRotSpeedPtr() {
00206     return &rotSpeed;
00207 }
 All Classes Files Functions Variables Enumerations