I'm having trouble with my project for loading a texture map onto a model. Any insight into what is going wrong with my code is fantastic. Right now the code only renders a teapot which I have assinged after creating it in 3DS Max.
3dsloader.cpp
#include "3dsloader.h"
Object::Object(std:: string filename)
{
m_TotalFaces = 0;
m_model = lib3ds_file_load(filename.c_str());
// If loading the model failed, we throw an exception
if(!m_model)
{
throw strcat("Unable to load ", filename.c_str());
}
// set properties of texture coordinate generation for both x and y coordinates
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
// if not already enabled, enable texture generation
if(! glIsEnabled(GL_TEXTURE_GEN_S))
glEnable(GL_TEXTURE_GEN_S);
if(! glIsEnabled(GL_TEXTURE_GEN_T))
glEnable(GL_TEXTURE_GEN_T);
}
Object::~Object()
{
if(m_model) // if the file isn't freed yet
lib3ds_file_free(m_model); //free up memory
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}
void Object::GetFaces()
{
m_TotalFaces = 0;
Lib3dsMesh * mesh;
// Loop through every mesh.
for(mesh = m_model->meshes;mesh != NULL;mesh = mesh->next)
{
// Add the number of faces this mesh has to the total number of faces.
m_TotalFaces += mesh->faces;
}
}
void Object::CreateVBO()
{
assert(m_model != NULL);
// Calculate the number of faces we have in total
GetFaces();
// Allocate memory for our vertices and normals
Lib3dsVector * vertices = new Lib3dsVector[m_TotalFaces * 3];
Lib3dsVector * normals = new Lib3dsVector[m_TotalFaces * 3];
Lib3dsTexel* texCoords = new Lib3dsTexel[m_TotalFaces * 3];
Lib3dsMesh * mesh;
unsigned int FinishedFaces = 0;
// Loop through all the meshes
for(mesh = m_model->meshes;mesh != NULL;mesh = mesh->next)
{
lib3ds_mesh_calculate_normals(mesh, &normals[FinishedFaces*3]);
// Loop through every face
for(unsigned int cur_face = 0; cur_face < mesh->faces;cur_face++)
{
Lib3dsFace * face = &mesh->faceL[cur_face];
for(unsigned int i = 0;i < 3;i++)
{
memcpy(&texCoords[FinishedFaces*3 + i], mesh->texelL[face->points[ i ]], sizeof(Lib3dsTexel));
memcpy(&vertices[FinishedFaces*3 + i], mesh->pointL[face->points[ i ]].pos, sizeof(Lib3dsVector));
}
FinishedFaces++;
}
}
// Generate a Vertex Buffer Object and store it with our vertices
glGenBuffers(1, &m_VertexVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Lib3dsVector) * 3 * m_TotalFaces, vertices, GL_STATIC_DRAW);
// Generate another Vertex Buffer Object and store the normals in it
glGenBuffers(1, &m_NormalVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_NormalVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Lib3dsVector) * 3 * m_TotalFaces, normals, GL_STATIC_DRAW);
// Generate a third VBO and store the texture coordinates in it.
glGenBuffers(1, &m_TexCoordVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_TexCoordVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Lib3dsTexel) * 3 * m_TotalFaces, texCoords, GL_STATIC_DRAW);
// Clean up our allocated memory
delete vertices;
delete normals;
delete texCoords;
// We no longer need lib3ds
lib3ds_file_free(m_model);
m_model = NULL;
}
void Object::applyTexture(const char*texfilename)
{
float imageWidth;
float imageHeight;
glGenTextures(1, & textureObject); // allocate memory for one texture
textureObject = SOIL_load_OGL_texture(texfilename,SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID,SOIL_FLAG_MIPMAPS);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glBindTexture(GL_TEXTURE_2D, textureObject); // use our newest texture
glGetTexLevelParameterfv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&imageWidth);
glGetTexLevelParameterfv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&imageHeight);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // give the best result for texture magnification
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //give the best result for texture minification
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // don't repeat texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // don't repeat textureglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // don't repeat texture
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,& textureObject);
}
void Object::Draw() const
{
// Enable vertex, normal and texture-coordinate arrays.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Bind the VBO with the normals.
glBindBuffer(GL_ARRAY_BUFFER, m_NormalVBO);
// The pointer for the normals is NULL which means that OpenGL will use the currently bound VBO.
glNormalPointer(GL_FLOAT, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, m_TexCoordVBO);
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexVBO);
glVertexPointer(3, GL_FLOAT, 0, NULL);
// Render the triangles.
glDrawArrays(GL_TRIANGLES, 0, m_TotalFaces * 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
3dsloader.h
#include "main.h"
#include "lib3ds/file.h"
#include "lib3ds/mesh.h"
#include "lib3ds/material.h"
class Object
{
public:
Object(std:: string filename);
virtual ~Object();
virtual void Draw() const;
virtual void CreateVBO();
void applyTexture(const char*texfilename);
protected:
void GetFaces();
unsigned int m_TotalFaces;
Lib3dsFile * m_model;
Lib3dsMesh* Mesh;
GLuint textureObject;
GLuint m_VertexVBO, m_NormalVBO, m_TexCoordVBO;
};
Called in the main cpp file with: VBO,apply texture and draw (pretty simple, how ironic)
and thats it, please help me forum :)