CPSC362A
Video Game Development

Project Part 1

Model Files

Create the class Model that represents a 3D model.

Details

The Model class should:

  1. 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.

  2. Define the method void Draw() const that uses an OpenGL vertex array and glDrawElements to draw the model with a fixed color. The method should do nothing if there is no window whose OpenGL context is current.

  3. Define the default constructor, Model(), to create a model with no loaded geometry.

  4. Define the constructor Model(const std::string &filepath) that creates a model with the geometry in the specified file by calling the load 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.