Create the class Model
that represents a 3D model.
Details
The Model
class should:
Define the method
void Load(const std::string &filepath)
that loads the specified Wavefront .obj file vertex and face data into memory. If the object already has vertex and face data loaded, calling this method should replace the existing data with the data in the specified file. The method can assume that all faces are triangles and that no face lines contain slash characters. If any errors are encountered while parsing the file, the method should print an error and set member data such that no file has been loaded.The method should handle files that contain information not currently used by ignoring all lines that do not start with a v or an f. It should handle any amount or type of whitespace before or after values.
Define the method
void Draw() const
that uses an OpenGL vertex array andglDrawElements
to draw the model with a fixed color. The method should do nothing if there is no window whose OpenGL context is current.Define the default constructor,
Model()
, to create a model with no loaded geometry.Define the constructor
Model(const std::string &filepath)
that creates a model with the geometry in the specified file by calling theload
method.
Your code can use any library in the C++ Standard 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
├──src
| └──engine
| ├──model.cc
| ├──model.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"
int main() {
// Initialize GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
// Create a windowed mode window and its OpenGL context
GLFWwindow* window = glfwCreateWindow(640, 480, "Test", NULL, NULL);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Clear the color buffer to black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// Enable depth testing
glEnable(GL_DEPTH_TEST);
// Create and load model
engine::Model model("data/model1.obj");
// Loop until the user closes the window
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
!glfwWindowShouldClose(window)) {
// Set the rendering viewport location and dimensions
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Clear the color and depth buffers before drawing
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Select and setup the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float ratio = width / static_cast<float>(height);
glOrtho(-ratio, ratio, -1.0f, 1.0f, 1.0f, -1.0f);
// Select and setup the modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Draw model
model.Draw();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
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 | load function can load a .obj file | 40 points |
2 | load function replaces existing loaded data | 5 points |
3 | load function ignores comment lines | 5 points |
4 | load function handles invalid file names | 5 points |
5 | load function ignores vt, vn, vp, and l, lines | 5 points |
6 | load function handles extra whitespace and tabs | 5 points |
7 | load function handles w coordinates | 5 points |
8 | load function handles interlaced v and f lines | 5 points |
9 | load function handles malformed v line | 5 points |
10 | load function handles malformed f line | 5 points |
11 | draw function draws using glDrawElements |
5 points |
12 | constructors initialize empty and loaded model | 5 points |
13 | can draw multiple models simultaneously | 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 / 35.0 * 100.0), 0.0), 125.0);
Submission
Submit a .zip file with the following structure and contents:
username
├──model.cc
└──model.h
where username
is your cpsc user name.
Submit your .zip file on Inquire before class on Friday, March 20th.