Question
Overview Write a program that changes how a model is rendered and computes an axis aligned bounding box, which in the future can be use
Overview
Write a program that changes how a model is rendered and computes an axis aligned bounding box, which in the future can be use for operations like collision detection. This assignment is also intended to teach you about OpenGL program flow.
To Do:
Calculate the axis aligned bounding box AABB for the model.
(15pts) To calculate an AABB: simply loop through all the models vertices, and store the x,y,z values if they are the min and max x,y,z values. That is, you must find the min and max x, the min and max y, and the min and max z. To do this, inside the Model class you will need to interact with the shapes object to get at the position data. For example, in the Model class, youd say shapes[0].mesh.positions to get at the vertex position data. Here is how the vertex position data is stored in the positions vector
[x1,y1,z1,x2,y2,z2,x3, y3,z3, xn,yn,zn ]
Where (x1,y1,z1) is the first vertexs position in 3D.
Here is an example of an axis aligned bounding box around a torus. NOTE: I pulled this off of Google images to show you what an AABB looks like. You program will not look exactly like this.
(15pts) To render the AABB: Take the mins and maxes from part a, and turn them into 8 vertices, and a list of indices stored in a tinyobj::shape object. Also, make sure to set a default values for the normals as (1.0, 0.0, 0.0). Otherwise you might get some weird errors when you render!
To do this part efficiently, Id suggest either making a subclass of Model or modify the Model class to support this functionality. Then, you can just change the render function to call glDrawElements with GL_LINES as the first parameter.
GL_LINES works differently than the current GL_TRIANGLES. See https://www.opengl.org/wiki/Primitive for an explanation. Thus, you will need to organize your vertices and indices for GL_LINES to produce the desired result.
Keyboard controls (10 pts)
b: toggle the bounding box on and off
w: toggle wireframe mode. If on, this should render the model as a wireframe. To do this, you must call
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);
To make it solid again you call:
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);
Model.h:
#include
/*This class represents a mesh - a collection of triangles. It stores a list of vertices, which are interpreted by openGL as every 3 vertices makes a triangle.*/ class Model{
public:
/*This struct represents a vertex in 3D space*/ struct Vertex { Vertex() : Position(0.0f,0.0f,0.0f), Normal(0.0f,0.0f,1.0f){} // default values glm::vec3 Position; /// x,y,z glm::vec3 Normal; // determines which way the vertex is 'facing'
};
Model(Shader *shader, const char* filename); //load a model ~Model(void){} // default destructor void render(glm::mat4 ModelView, glm::mat4 Projection); // render the model private: Shader *m_shader; // shader program std::vector<:shape_t> shapes; //a list of meshes and their respective materials std::vector
void updateBuffers(); //initialize your VBO and update when triangles are added };
Model.ccp:
#include "Model.h"
Model::Model(Shader *shader, const char* filename) { m_shader = shader; tinyobj::LoadObj(shapes,filename); for(int i = 0; i
/* Render the mesh to the screen @param Modelview - the model view matrix that defines where the camera is looking @param Projection - the projection matrix that defines how 3D vertices are projected on the 2D screen. */ void Model::render(glm::mat4 ModelView, glm::mat4 Projection) {
m_shader->Activate(); // Bind shader. //update the variables in the shader program m_shader->SetUniform("Projection", Projection); // send projection to vertex shader m_shader->SetUniform("ModelView", ModelView); // send modelview to vertex shader m_shader->SetUniform("lightPosition", glm::vec4(1.0, 0.0, 0.0, 1.0)); // send light position to vertex shader for(int i = 0; i DeActivate(); // Unbind shader. }
/*When a new vertex is added, you need to tell the VBO about it.*/ void Model::updateBuffers() { for(int i =0; i
}
main.cpp:
#include
//glm library #include
#include "Model.h" #include "Shader.h" #include
Shader shader; // loads our vertex and fragment shaders Model *myModel; //our myModel we want to draw Model *myModel2; //our myModel we want to draw glm::mat4 projection; // projection matrix glm::mat4 view; // where the camera is looking glm::mat4 model; // where the model (i.e., the myModel) is located wrt the camera
/* report GL errors, if any, to stderr */ void checkError(const char *functionName) { GLenum error; while (( error = glGetError() ) != GL_NO_ERROR) { std::cerr
void initShader(void) { //regular phong shading shader.InitializeFromFile("shaders/phong.vert", "shaders/phong.frag"); shader.InitializeFromFile("shaders/phong.vert", "shaders/green.frag"); shader.AddAttribute("vertexPosition"); shader.AddAttribute("vertexNormal");
checkError ("initShader"); }
void initRendering(void) { glClearColor (0.117f, 0.565f, 1.0f, 0.0f); // Dodger Blue checkError ("initRendering"); }
void init(void) { // Perspective projection matrix. projection = glm::perspective(45.0f, 800.0f/600.0f, 1.0f, 1000.0f);
// View matrix positioned at 100 on the z axis, looking into the screen down the -Z axis. view = glm::lookAt(glm::vec3(0.0f, 0.0f, 20.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// Load identity matrix into model matrix (no initial translation or rotation) model = glm::mat4();
initShader (); initRendering (); }
/* This prints in the console when you start the program*/ void dumpInfo(void) { printf ("Vendor: %s ", glGetString (GL_VENDOR)); printf ("Renderer: %s ", glGetString (GL_RENDERER)); printf ("Version: %s ", glGetString (GL_VERSION)); printf ("GLSL: %s ", glGetString (GL_SHADING_LANGUAGE_VERSION)); checkError ("dumpInfo"); }
/*This gets called when the OpenGL is asked to display. This is where all the main rendering calls go*/ void display(void) {
//glm::rot glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); myModel->render(view * model, projection); // Render current active model. myModel2->render(view * glm::translate(-5.0f,0.0f,0.0f), projection); // Render current active model. glutSwapBuffers(); // Swap the buffers. checkError ("display"); }
/*This gets called when nothing is happening (OFTEN)*/ void idle() { glutPostRedisplay(); // create a display event. Display calls as fast as CPU will allow when put in the idle function }
/*Called when the window is resized*/ void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); checkError ("reshape"); }
/*Called when a normal key is pressed*/ void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: // this is an ascii value exit(0); break; } }
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE| GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize (800, 600); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); glewInit(); dumpInfo (); init (); glutDisplayFunc(display); glutIdleFunc(idle); glutReshapeFunc(reshape); glutKeyboardFunc (keyboard); glEnable(GL_DEPTH_TEST);
myModel = new Model(&shader, "models/torus.obj"); myModel2 = new Model(&shader, "models/cube.obj");
glutMainLoop();
return 0; }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started