Create classes for game objects Camera
and RigidBody
.
Details
The Camera
and RigidBody
classes have functionality in common, so they should both inherit from an abstract class GameObject
.
The GameObject
class should:
Have protected member data:
glm::vec3 position
the position of the game object stored as a 3D point.glm::quat orientation
the orientation of the game object stored as a 3D quaternion.
Define the default constructor,
GameObject()
that sets the position to the origin and the orientation to the identity.Define setters for the member data:
void SetPosition(glm::vec3 position)
set the game object’s current position to the specified position point.void SetOrientation(glm::quat orientation)
set the game object’s current orientation to the specified quaternion orientation.void SetOrientation(float angle, glm::vec3 axis)
set the game object’s current orientation to the specified axis-angle orientation. The parameterangle
is in degrees.
Define getters for the member data:
glm::vec3 GetPosition() const
return the game object’s current position as a point.glm::quat GetOrientation() const
return the game object’s current orientation as a quaternion.
Define mutators for the member data:
void Move(glm::vec3 distance)
that changes the game object’s current position by moving it relative to its current position and orientation by the specified vector.void Turn(GLfloat angle, glm::vec3 axis)
that changes the game object’s current orientation by turning it relative to its current orientation by the specified angle, in degrees, around the specified vector.void LookAt(glm::vec3 eye, glm::vec3 center, glm::vec3 up)
that changes the game object’s current position and orientation. The position should be set to the specified eye position. The orientation should be set so that it “looks at” the specified center position with the specified up vector. A game object “looks at” a point by orienting so that the negative z-axis points from the eye position to the center position. Use theglm::lookAt
function to compute the orientation, but note thatglm::lookAt
is meant for camera transformations so it computes the inverse or the desired orientation.
The Camera
class should:
Inherit from the
GameObject
class.Define a constructor
Camera(GLfloat fovy, GLfloat zNear, GLfloat zFar)
that creates a camera with the specified view frustum. The parameterfovy
is the degrees of the full field of view in the y dimension. It should assert that all three parameters are positive.Define the mutator
void Zoom(GLfloat angle)
that changes the camera’s field of view by the specified angle in degrees.Define the method
void MultProjectionMatrix(int width, int height) const
that multiplies the camera’s projection matrix, calcluated using it’s current view frustum and the specified window width and height in pixels, with the current matrix.Define the method
void MultViewMatrix() const
that multiplies the camera’s current view matrix, calculated usings it’s current position and orientation, with the current matrix.
The RigidBody
class should:
Inherit from the `GameObject class.
Define a constructor
RigidBody(Model const *model)
that creates a rigid body with the specified model.Define a method
void Draw() const
that draws the rigid body’s model with it’s current position and orientation. Note, this will require making the model’ Draw function a const function as well.
Your code can use any library in the C++ Standard Library and the OpenGL Mathematics Library.
Your code should work on the lab computers. Test to verify.
Your code should be clean, readable, and efficient. Follow the Google C++ Style Guide for help with style. Use the cpplint tool to help check your code.
All classes should be declared inside of a namespace called engine
.
Your project should have the following directory structure:
project
├──data
| ├──model1.obj
| ├──model2.obj
| ├──model3.obj
| └──...
├──makefile
├──lib
| └──glm
| ├──gtc
| ├──gtx
| └──vec3.hpp
├──src
| └──engine
| ├──camera.cc
| ├──camera.h
| ├──game_object.cc
| ├──game_object.h
| ├──model.cc
| ├──model.h
| ├──rigid_body.cc
| └──rigid_body.h
└──test
├──test1.cc
├──test2.cc
├──test3.cc
└──...
Your project should compile and run with this makefile.
Example
#include <cstdlib>
#include <cstdio>
#include "GLFW/glfw3.h"
#include "engine/model.h"
#include "engine/rigid_body.h"
#include "engine/camera.h"
int main() {
// Initialize GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
// Create window
GLFWwindow* window = glfwCreateWindow(640, 480, "Test", NULL, NULL);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
// Initialize OpenGL
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
// create rigid body and camera
engine::Model model("data/model1.obj");
engine::RigidBody rigidBody(&model);
engine::Camera camera(35.0f, 0.1f, 10.0f);
camera.LookAt(glm::vec3(0.0f, 0.0f, 5.0f), // eye
glm::vec3(0.0f, 0.0f, 0.0f), // center
glm::vec3(0.0f, 1.0f, 0.0f)); // up
// Loop until the user closes the window
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
!glfwWindowShouldClose(window)) {
// Set the rendering viewport
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Select and setup the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
camera.MultProjectionMatrix(width, height);
// Select and setup the view matrix
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
camera.MultViewMatrix();
// Rotate and draw rigid body
rigidBody.Turn(10.0f, glm::vec3(0.0f, 1.0f, 0.0f)); // 10 deg around y axis
rigidBody.Draw();
// Prepare for next frame
glPopMatrix();
glfwSwapBuffers(window);
glfwPollEvents();
}
// Clean up
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Grading
The functionality of your code will be graded according to the following point scale:
1 | construct default GameObject and get position | 5 points |
2 | construct default GameObject and get orientation | 5 points |
3 | set GameObject position to point | 5 points |
4 | set GameObject orientation to quaternion orientation | 5 points |
5 | set GameObject orientation to axis-angle orientation | 5 points |
6 | move GameObject from the origin point | 5 points |
7 | move GameObject from arbitrary point | 5 points |
8 | turn GameObject from identity orientation | 5 points |
9 | turn GameObject from arbitrary orientation | 5 points |
10 | move and turn GameObject from origin and identity orientation with lookAt | 5 points |
11 | move and turn GameObject from arbitrary point and orientation with lookAt | 5 points |
12 | construct Camera and multiply the projection matrix | 5 points |
13 | zoom Camera and multiply the projection matrix | 5 points |
14 | construct Camera and multiply the view matrix | 5 points |
15 | move Camera and multiply the view matrix | 5 points |
16 | turn Camera and multiply the view matrix | 5 points |
17 | construct a RigidBody and draw | 5 points |
18 | move RigidBody and draw | 5 points |
19 | turn RigidBody and draw | 5 points |
20 | move and turn 2 RigidBody objects sharing a model and draw | 5 points |
The final grade for this part of the project will be computed as:
const double final_score = fmin(fmax(functionality_score - (days_late / 28.0 * 100.0), 0.0), 125.0);
Submission
Submit a .zip file with the following structure and contents:
username
├──camera.cc
├──camera.h
├──game_object.cc
├──game_object.h
├──model.cc
├──model.h
├──rigid_body.cc
└──rigid_body.h
where username
is your cpsc user name.
Submit your .zip file on Inquire before class on Friday, March 27th.