Waterflow
Visualize water in terrain
|
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 }