Lab 5: A Camera Class, World Navigation, Perspective

Due Sunday, 12 October 2025

This is a partnered lab assignment and a continuation of last week’s lab. There is no new repo to clone. Please work with the same partner and push to the same repo for this week.

1. Lab Goals

Through this lab you will learn to

  • Use an Perspective projection transform to convert from a 3D world coordinate system suitable for a 3D solar system model to webGL2 clip coordinates.

  • Build a Camera class and construct your own LookAt/View matrix

  • Navigate through the scene by moving the camera with translations and rotations.

  • Use signals and slots to interact with the user.

1.1. LearnOpenGL

  • Camera motion - This link has another derivation of the lookAt matrix. They also talk a bit about a Camera model translation and rotation effects. The figures may be helpful, but the code uses GLM and glfw and doesn’t transfer easily to our Qt setup.

2. Overview

If you have not completed lab 4, you can continue working on lab 4 features, but you can do the lab 5 components even if you have a single sphere from the lab 4 starter code. Labs 4 and 5 will receive separate grades. For this lab you will add a camera class and some keyboard or mouse interaction to manipulate the camera. Additionally, you will switch your orthographic projection to a perspective projection for a better sense of 3D depth.

2.1. Code setup

Copy over the camera.h header file and add it to your git repo. As usual, only one partner needs to do the initial copy, add, commit, and push, while the other can pull the changes

[~]$ cd ~/cs40/lab04-you-partner
[lab04]$ cp ~adanner/public/cs40/lab05/* ./

Edit your lab04/CMakeLists.txt file to add camera.h to your program sources. Eventually you will also want to add camera.cpp, but since this file does not exist yet, do not add it until you start implementing your camera class.

target_sources(${PROGNAME} PRIVATE
  ...
  camera.h camera.cpp
  shaders/vshader.glsl shaders/fshader.glsl
)
[lab04]$ git add CMakeLists.txt camera.h README5.md
[lab04]$ git commit -m "lab 5 camera class start"
[lab04]$ git push

2.1.1. Changing your vertex shader

You will need to implement the Camera class as described. You can add additional methods/member variables, but do not remove the method declarations already in the header.

Use your camera class to specify the camera location for the vertex shader. Add a new uniform mat4 camera variable to your vertex shader. You may want to change the name view to projection as view is a bit more ambiguous in this lab. Your new shader can be as simple as follows

#version 410

uniform vec4 vColor;
uniform mat4 model;
uniform mat4 camera;
uniform mat4 projection;

in vec4 vPosition;
in vec2 vTexture;

out vec4 color;
out vec2 texCoord;

void main(){
    gl_Position = projection*camera*model*vPosition;
    color = vColor;
    texCoord = vTexture;
}

To test the transition to the new shader variables, I recommend the following process:

  1. Change m_view in your MyPanelOpenGL class to be something like m_project. This can be a simple search/replace in the .h/.cpp files.

  2. Temporarily in paintGL create a QMatrix4x4 object storing the identity matrix. Connect this matrix to the uniform variable camera in the vertex shader, prior to setting the model matrices for your planets.

  3. Change the name of the uniform variable view in your vertex shader to projection.

  4. Test that your scene appears as before.

3. Writing a Camera Class

The primary goals of implementing the camera class are to understand how to construct the lookAt matrix from scratch, and how to manipulate the camera to support panning and rotating from the camera’s perspective. Use the inclass notes to implement lookAt and feel free to check your solution against QMatrix4x4::lookAt. The Learn OpenGL Tutorial has some suggestions on how to implement camera panning and rotating methods, but you can feel free to design your own implementation.

Once you have you have your Camera implemented and compiled, you can begin testing it by adding a cs40::Camera object to your MyPanelOpenGL class. Think about a good default value for your lookAt given your solar system scene and set this viewpoint in initializeGL. Then connect your camera’s lookAt matrix to the shader, by replacing the camera uniform value with a call to the matrix() method of your cs40::Camera object.

This could potentially be a very large change to the scene and everything may disappear. Note that your projection matrix (which is probably still your original ortho matrix), is now projecting eye coordinates, not world coordinates. At this point, I would strongly encourage you to modify the last two parameters of ortho to be the distances to the near and far clipping planes with 0 < near < far. These distances are measured as distances in front of the eye. Making this change with the ortho box now will help you when you transition to a perspective projection later. I suggest a small positive value for the near value like 100 and a larger value for the far z value like 10000, but this depends on your scale a little bit.

Test your implementation by trying a couple different viewpoints similar to that of the w04 demo.

3.1. Navigating the scene

Add keyboard, mouse, or button controls to support the following:

  • Camera Panning (left,right,up,down,forward back)

  • Camera Rotation (roll, pitch, yaw)

  • Reset Camera to original default location (at start of program)

Implement the camera.h translation methods as described. Note half of them are implemented as just opposites of the other half. Think about how you want to implement this and what state you want to maintain in your camera class. Do you want to explicitly maintain an eye, at, and up vector in your class? If so, which variables change when you move, e.g., up?

Document your camera controls. The method showOptions prints the keyboard controls to the screen so the user does not need to read the source to figure out how to navigate. Updating this method to reflect your changes is sufficient documentation.

Keep in mind the amt and deg amounts are relative, not absolute, so you can say roll(10) three times to rotate 30 degrees.

For an extra optional challenge, you can use mouse events to implement a virtual trackball. This is not required for full credit.

Whatever controls you choose, you should be able to navigate your scene with your camera control. You should be able to e.g., turn to look at Neptune and move closer to it, or move above the solar plane and look down.

4. Changing the projections to Perspective

Given the scale of the solar system, the scene looks a bit more realistic with a perspective projection that makes further away objects appear smaller. Modify your code so that the m_project matrix uses QMatrix4x4::perspective transform instead of an ortho transform. You will likely need to experiment to find good values for these parameters.

Once you have sensible defaults in initializeGL, add keyboard, or button controls to support the following:

  • Change of perspective angle

  • Reset perspective settings to default (set in initializeGL)

5. Additional required feature

In addition to the core requirements of implementing the camera class and adding a perspective projection, you must add some additional feature to this lab that can be of your choosing, but should deal with camera motion. The following are possible extensions to the basic requirements. For full credit, you should implement one of these extensions, or get approval for an extension not on the list.

  • Add Camera support for pivoting around the at location. Thus if you pitch around at, you can circle around a fixed point, instead of circling around the camera center. Have at follow the center of a planet for some nice planetary exploration tools.

  • Implement a virtual trackball. Feeling super adventurous? Try quaternions. Feeling invincible? Implement your own Quaternion class.

  • Add a 'walking effect'. When moving forward/back, add a small sinusoidal vertical displacement, so you 'bounce' while traversing through space.

  • Add an 'Earthquake mode' where you just perturb the camera in random directions for a period of time. You can even modulate the magnitude of the perturbation so the shaking starts of slow, intensifies, and then decays. Don’t worry about what 'Earthquake' means in the context of space exploration.

6. Readme5.adoc

Answer the questions in the README5.adoc file in that you copied earlier

7. Summary of Requirements

Your project will be graded on the following components:

  • A Camera class with working navigation

  • A properly constructed view matrix that does not use QMatrix4x4::lookAt

  • Keyboard or mouse controls for translation and rotation of the camera

  • A perspective projection matrix.

  • Answer to concept questions in the Readme.adoc file.

You will not be graded on the lab survey questions in the Readme.adoc file

8. Submit

Once you have edited the files, you should publish your changes using add, commit and push.

The git push command sends your committed changes to the github server. If you do not run git push before the submission deadline, I will not see your changes, even if you have finished coding your solution in your local directory.

If you make changes to files after your push and want to share these changes, repeat the add, commit, push loop again to update the github server.

If you want to commit changes to files that have already been committed to git once, you can combine the add and commit steps using

$ git commit -am "bug fix/updates"

The -a flag will automatically add files that have been previously committed. It will not add new files. When in doubt, use git status, and please do not use git add * ./

Please do not add your symlink to the data folder to the git repo. I have it set to be ignored, and it may create conflicts if partners are working with different links.