Anonymous Anonymous - 8 days ago
93 0

Ok so this is the quick and dirty method to get it working, theres probably 100 better ways to do it (such as splitting up the data into nicer vertex's that dont require stupid magic numbers to work) but this is probably what I'll be handing in. The file loader basically takes the verts, normals and texture coords and saves them in a 3 different vectors containing Vector3's (contains (x,y,z)). the index vector then fetches the different face values (e.g. the 3 vertexs that create a face). These vectors are then passed into the render function that uses magic numbers to draw the correct information, in the correct order. The for loop then moves forward by 9 (3 vertex vectors, 3 normal vectors, 3 texture vectors) and continues until there are no more face to be drawn. The file is then called by using
"modeltest.load("models/teapot.obj", "models/crate.png");" in your scene constructor (NOTE: Dont use this code during any stage of your program that is updated once per frame (Causes a shit tone of lag)
and use
"modeltest.render(); to draw the object (NOTE: "modeltest" is a object of class Model and is defined in Scene.h

C++

Modeler Code Dump

void Model::render()
{
	// TODO: Need to add code here to render the loaded model
	// How this is done is based on how you stored and sorted the data

	//Set Up the Texture that's been loaded in from the file
	glBindTexture(GL_TEXTURE_2D, texture);	//tells opengl which texture to use
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_LINEAR);

	//Begin Drawing (NOTE: THIS WILL ONLY WORK WITH MODELS THAT USE TRIANGLES
	glBegin(GL_TRIANGLES);
	for (int e = 0; e < faces.size(); e+=9)
		{	
			//Draw the first vertex (index[e] is the vertex, index[e+1] is the texture coord, index[e+2] is the normal)
			glNormal3f(norms[indexs[e + 2] - 1].x, norms[indexs[e + 2] - 1].y, norms[indexs[e + 2] - 1].z);
			glTexCoord3f(texCs[indexs[e + 1] - 1].x, texCs[indexs[e + 1] - 1].y, texCs[indexs[e + 1] - 1].z);
			glVertex3f(verts[indexs[e] - 1].x, verts[indexs[e] - 1].y, verts[indexs[e] - 1].z);

			//Draw next vertex (NOTE: the values for the index is offset to move "point" to the next vertex's information)
			glNormal3f(norms[indexs[e + 5] - 1].x, norms[indexs[e + 5] - 1].y, norms[indexs[e + 5] - 1].z);
			glTexCoord3f(texCs[indexs[e + 4] - 1].x, texCs[indexs[e + 4] - 1].y, texCs[indexs[e + 4] - 1].z);
			glVertex3f(verts[indexs[e + 3] - 1].x, verts[indexs[e + 3] - 1].y, verts[indexs[e + 3] - 1].z);

			//Draw the final vertex
			glNormal3f(norms[indexs[e + 8] - 1].x, norms[indexs[e + 8] - 1].y, norms[indexs[e + 8] - 1].z);
			glTexCoord3f(texCs[indexs[e + 7] - 1].x, texCs[indexs[e + 7] - 1].y, texCs[indexs[e + 7] - 1].z);
			glVertex3f(verts[indexs[e + 6] - 1].x, verts[indexs[e + 6] - 1].y, verts[indexs[e + 6] - 1].z);
		}

	glEnd();

// Modified from a mulit-threaded version by Mark Ropper.
bool Model::loadModel(char* filename)
{
	
	FILE* file = fopen(filename, "r");
	if (file == NULL)
	{
		return false;
	}
	while (true)
	{
		char lineHeader[128];

		// Read first word of the line
		int res = fscanf(file, "%s", lineHeader);
		if (res == EOF)
		{
			break; // exit loop
		}
		else // Parse
		{
			if (strcmp(lineHeader, "v") == 0) // Vertex
			{
				Vector3 vertex;
				fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
				verts.push_back(vertex);
				m_vertexCount++;
			}
			else if (strcmp(lineHeader, "vt") == 0) // Tex Coord
			{
				Vector3 uv;
				fscanf(file, "%f %f\n", &uv.x, &uv.y);
				texCs.push_back(uv);
			}
			else if (strcmp(lineHeader, "vn") == 0) // Normal
			{
				Vector3 normal;
				fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
				norms.push_back(normal);
			}
			else if (strcmp(lineHeader, "f") == 0) // Face
			{
				unsigned int face[9];
				int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &face[0], &face[1], &face[2],
																			&face[3], &face[4], &face[5],
																			&face[6], &face[7], &face[8]);
				if (matches != 9)
				{
					// Parser error, or not triangle faces
					return false;
				}
				
				for (int i = 0; i < 9; i++)
				{
					faces.push_back(face[i]);
				}


			}
		}
	}

	// "Unroll" the loaded obj information into a list of triangles.
	// TODO: By this point all model has been read from the file, but is not in the correct order.
	// You NEED to loop over all the data and sort it into a render ready order/format.

	for (int counter = 0; counter < verts.size(); counter++)
	{

		vertex.push_back(verts[counter].x);
		vertex.push_back(verts[counter].y);
		vertex.push_back(verts[counter].z);

		normals.push_back(norms[counter].x);
		normals.push_back(norms[counter].y);
		normals.push_back(norms[counter].z);

		texCoords.push_back(texCs[counter].x);
		texCoords.push_back(texCs[counter].y);
		texCoords.push_back(texCs[counter].z);

	}

	for (int counter = 0; counter < faces.size(); counter++)
	{
		indexs.push_back(faces[counter]);
	}
	
	// Once data has been sorted clear read data (which has been copied and are not longer needed).
	/*
	verts.clear();
	norms.clear();
	texCs.clear();
	faces.clear();
	*/

	return true;
}


// Model class, represents a loaded OBJ model
// handles the loading/processing of the model file. Also loads and stores its own texture
// NOT complete, for students to complete. Model data requires being sorted and the render function needs completed.
#ifndef _MODEL_H_
#define _MODEL_H_

// INCLUDES //
#include <glut.h>
#include <fstream>
#include <gl/gl.h>
#include <gl/glu.h>

using namespace std;

// MY CLASS INCLUDES //
#include <vector>
#include "Vector3.h"
#include "SOIL.h"

class Model
{


public:

	bool load(char* modelFilename, char* textureFilename);
	void render();
	int m_vertexCount = 0;

	vector<GLfloat> vertex, normals, texCoords;
	vector<int> indexs;

	vector<Vector3> verts;
	vector<Vector3> norms;
	vector<Vector3> texCs;
	vector<unsigned int> faces;

private:

	void loadTexture(char*);
	bool loadModel(char*);

	GLuint texture;

};

#endif