Browse Source

Added Camera controls and zoom.

angel 7 years ago
parent
commit
2971a7aaa9
5 changed files with 83 additions and 70 deletions
  1. 5 2
      include/camera.h
  2. 1 1
      include/geometry.h
  3. 13 4
      src/camera.cpp
  4. 18 9
      src/geometry.cpp
  5. 46 54
      src/inputManager.cpp

+ 5 - 2
include/camera.h

@@ -11,8 +11,9 @@ struct Camera{
     
     bool checkVisibility(AABox *bounds);
 
-    //In the future user input should control this. For now just simple movement
+    //Updates the camera matrices with the user input obtained in the input class
     void update(unsigned int deltaT);
+    void resetCamera();
 
     Matrix4 viewMatrix;
     Matrix4 projectionMatrix;
@@ -25,11 +26,13 @@ struct Camera{
     Vector3f side;
 
     //Values related to orbiting mode
-    float radius = 2;
+    float radius  = 2;
     bool orbiting = false;
 
     //Momentary fixed camera speed (FPS dependent)
     float camSpeed = 0.1f;
+    float pitch    = 0;
+    float yaw      = -90;
 
     Frustrum cameraFrustrum{DisplayManager::SCREEN_ASPECT_RATIO};
 };

+ 1 - 1
include/geometry.h

@@ -32,7 +32,7 @@ class Frustrum{
 		RIGHT, NEARP, FARP
         };
     public:
-        float  fov, AR, near, far , nearH, nearW, farH, farW;
+        float  fov, AR, near, far , nearH, nearW;
         Frustrum(float ratio): fov(50), near(0.1), far(100), AR(ratio){};
         Plane pl[6];
 

+ 13 - 4
src/camera.cpp

@@ -10,7 +10,7 @@ Camera::Camera(){
 
 void Camera::update(unsigned int deltaT){
     if(orbiting){
-        float ang = 2*M_PI*static_cast<float>(SDL_GetTicks())/3e4;
+        float ang    = 2 * M_PI * static_cast<float>(SDL_GetTicks()) / 3e4;
         float camX   = std::sin(ang) * radius; 
         float camZ   = std::cos(ang) * radius;
         position.x   = camX;
@@ -18,14 +18,23 @@ void Camera::update(unsigned int deltaT){
         position.z   = camZ;
     }
     else{
-        // target = front;
         target = position + front;
-
     }
-    viewMatrix   = Matrix4::lookAt(position,target,up);
+    viewMatrix = Matrix4::lookAt(position, target, up);
     cameraFrustrum.updatePlanes(viewMatrix, position);
+    projectionMatrix = Matrix4::projectionMatrix(cameraFrustrum.fov, cameraFrustrum.AR, cameraFrustrum.near, cameraFrustrum.far);
 }
 
 bool Camera::checkVisibility(AABox *bounds){
     return cameraFrustrum.checkIfInside(bounds);
+}
+
+void Camera::resetCamera(){
+    position = Vector3f(0, 0, 8.0);
+    target.zero();  
+    front    = Vector3f(0, 0, -1);
+    side     = front.crossProduct(up);
+    radius   =   2;
+    pitch    =   0;
+    yaw      = -90;
 }

+ 18 - 9
src/geometry.cpp

@@ -75,31 +75,40 @@ void Plane::setNormalAndPoint(const Vector3f &n, const Vector3f &p0){
 
 void Frustrum::setCamInternals(){
     float tanHalfFOV  =  tan( (fov/2) * (M_PI / 180) );
-    nearH = near * tanHalfFOV;
+    nearH = near * tanHalfFOV; //Half of the frustrum near plane height
     nearW = nearH * AR;
-
-    farH  = far * tanHalfFOV;
-    farW  = farH * AR;
 }
 
 //Calculates frustrum planes in world space
 void Frustrum::updatePlanes(Matrix4 &viewMat, const Vector3f &cameraPos){
-    Vector3f X(viewMat(0,0), viewMat(0,1), viewMat(0,2));
-    Vector3f Y(viewMat(1,0), viewMat(1,1), viewMat(1,2));
-    Vector3f Z(viewMat(2,0), viewMat(2,1), viewMat(2,2));
+    setCamInternals();
+    Vector3f X(viewMat(0,0), viewMat(0,1), viewMat(0,2)); //Side Unit Vector
+    Vector3f Y(viewMat(1,0), viewMat(1,1), viewMat(1,2)); //Up Unit Vector
+    Vector3f Z(viewMat(2,0), viewMat(2,1), viewMat(2,2)); //Forward vector
     
+    //Gets worlds space position of the center points of the near and far planes
+    //The forward vector Z points towards the viewer so you need to negate it and scale it
+    //by the distance (near or far) to the plane to get the center positions
     Vector3f nearCenter = cameraPos - Z * near;
     Vector3f farCenter  = cameraPos - Z * far;
 
     Vector3f point;
     Vector3f normal;
 
-    //Near plane 
+    //We build the planes using a normal and a point (in this case the center)
+    //Z is negative here because we want the normal vectors we choose to point towards
+    //the inside of the view frustrum that way we can cehck in or out with a simple 
+    //Dot product
     pl[NEARP].setNormalAndPoint(-Z, nearCenter);
     //Far plane 
     pl[FARP].setNormalAndPoint(Z, farCenter);
 
-    //Top plane
+    //Again, want to get the plane from a normal and point
+    //You scale the up vector by the near plane height and added to the nearcenter to 
+    //optain a point on the edge of both near and top plane.
+    //Subtracting the cameraposition from this point generates a vector that goes along the 
+    //surface of the plane, if you take the cross product with the direction vector equal
+    //to the shared edge of the planes you get the normal
     point  = nearCenter + Y*nearH;
     normal = (point - cameraPos).normalized();
     normal = normal.crossProduct(X);

+ 46 - 54
src/inputManager.cpp

@@ -99,20 +99,12 @@ void InputManager::handleEvent(SDL_Event * event, bool &done, unsigned int delta
 
             //CAMERA CONTROLS (RESET AND ORBITING)
             case SDLK_r:
-            sceneCamera->position = Vector3f(0, 0, 8.0);
-            sceneCamera->target.zero();  
-            sceneCamera->side = sceneCamera->front.crossProduct(sceneCamera->up);
-            sceneCamera->front = Vector3f(0, 0, -1);
-            sceneCamera->radius = 2;  
+            sceneCamera->resetCamera(); 
             break;
 
             case SDLK_TAB:
             sceneCamera->orbiting = !sceneCamera->orbiting;
-            sceneCamera->position = Vector3f(0, 0, 8.0);
-            sceneCamera->target.zero();
-            sceneCamera->side = sceneCamera->front.crossProduct(sceneCamera->up);
-            sceneCamera->front = Vector3f(0, 0, -1);
-            sceneCamera->radius = 2;    
+            sceneCamera->resetCamera();   
             break;
 
             default:
@@ -131,56 +123,56 @@ void InputManager::handleEvent(SDL_Event * event, bool &done, unsigned int delta
             else{
                 printf("Loaded %s Scene.\n", sceneID.c_str());
                 sceneCamera = (sceneController->getCurrentScene()->getCurrentCamera());
-                sceneCamera->position = Vector3f(0, 0, 8.0);
-                sceneCamera->target.zero();
-                sceneCamera->side = sceneCamera->front.crossProduct(sceneCamera->up);
-                sceneCamera->front = Vector3f(0, 0, -1);
-                
+                sceneCamera->resetCamera(); 
             }
 
         }
     }
     //Handling Mouse Motion
     else if( event->type == SDL_MOUSEMOTION){
-        float sens = 0.001f;
-        float xRot = -(float)event->motion.yrel * sens;
-        float yRot = -(float)event->motion.xrel * sens;
-
-        Matrix4 cameraRot = Matrix4::fullRotMat(xRot, yRot, 0.0f);
-
-        sceneCamera->front = cameraRot.matMultVec(sceneCamera->front).normalized();
-        sceneCamera->side  = cameraRot.matMultVec(sceneCamera->side).normalized();
-        
-        // Matrix4 camTransform = (sceneCamera->viewMatrix);
-        // Vector3f newDir      = Vector3f((float)event->motion.xrel*0.01f, -(float)event->motion.yrel*0.01f, 0.0f);
-        // Vector3f relMov      = camTransform.matMultDir(newDir);
-
-        // sceneCamera->front = (sceneCamera->front + relMov).normalized();
-        
-        // if(event->motion.xrel > 0){
-        //     sceneCamera->front = (sceneCamera->front + Vector3f((float)event->motion.xrel*0.001f, 0.0f, 0.0f)).normalized();
-        //     printf("Moved right!\n");
-            
-        // }
-
-        // if(event->motion.xrel < 0){
-            
-        //     printf("Moved left!\n");
-        // }
-
-        // if(event->motion.yrel > 0){
-        //     printf("Moved down!\n");
-        // }
-
-        // if(event->motion.yrel < 0){
-        //     printf("Moved up!\n");
-        // }
+        //Only move camera if the right button is pressed
+        if( event->motion.state & SDL_BUTTON_RMASK ) {
+            float sens = 0.05f;
+            float xOffset = (float)event->motion.xrel * sens;
+            float yOffset = -(float)event->motion.yrel * sens;
+
+            sceneCamera->yaw   += xOffset;
+            sceneCamera->pitch += yOffset;
+
+            //Limiting the range of the pitch to avoid flips
+            if(sceneCamera->pitch > 89.0f){
+                sceneCamera->pitch =  89.0f;
+            }
+            else if(sceneCamera->pitch < -89.0f){
+                sceneCamera->pitch = -89.0f;
+            }
+
+            //Updating the front and side vectors to allow wasd movement and 
+            //free camera movement.
+            sceneCamera->front.x = cos( sceneCamera->pitch * M_PI / 180.0f ) * cos( sceneCamera->yaw * M_PI / 180.0f );
+            sceneCamera->front.y = sin( sceneCamera->pitch * M_PI / 180.0f );
+            sceneCamera->front.z = cos( sceneCamera->pitch * M_PI / 180.0f ) * sin( sceneCamera->yaw * M_PI / 180.0f );
+            sceneCamera->front   = sceneCamera->front.normalized();
+            sceneCamera->side    = sceneCamera->front.crossProduct(sceneCamera->up);
+        }
     }
-}
+    else if( event->type == SDL_MOUSEWHEEL){
+        float zoom = 5.0f;
+        float fov  = sceneCamera->cameraFrustrum.fov; 
+        if(event->wheel.y > 0){ // scroll up
+            fov -= zoom;
+        }
+        else if(event->wheel.y < 0) {// scroll down
+            fov += zoom;
+        }
 
+        if(fov < 30){
+            fov = 20;
+        }
+        else if (fov > 120){
+            fov = 120;
+        }
 
-//Handling Mouse Input
-    // else if((event->type == SDL_MOUSEBUTTONDOWN) && (event->button.button == SDL_BUTTON_RIGHT)){
-    //     printf("Right mouse Click detected\n");
-    //     SDL_Delay(1000);
-    // }
+        sceneCamera->cameraFrustrum.fov = fov;
+    }
+}