lib3ds and texture mapping help

Adam_Burton 101 Apr 09, 2012 at 11:49 opengl

hi there

i have fixed up a few problems on my 3ds loader using lib3ds, my only problem now is that i have no idea how to load a texture map onto the loaded model. do i have to use lib3ds Material or something like that?


#include “main.h”
#include “lib3ds/file.h”
#include “lib3ds/mesh.h”
#include “lib3ds/material.h”

class Object
Object(const char* filename);
virtual \~Object();
virtual void Draw() const;
virtual void CreateVBO();
void applyTexture(const char*texfilename);

void GetFaces();
unsigned int m_TotalFaces;
Lib3dsFile * m_model;

Lib3dsMesh* Mesh;
GLuint textureObject;
GLuint m_VertexVBO, m_NormalVBO, m_TexCoordVBO;


#include "3dsloader.h"
#include "shader.h"[/size][/color][/font][/left]
[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]Object::Object(const char* filename)
m_TotalFaces = 0;
m_model = lib3ds_file_load(filename);
// If loading the model failed, we throw an exception
  cout << ("Unable to load ", filename);
Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(m_model,"filename");[/size][/color][/font]

[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]}
if(m_model) // if the file isn't freed yet
  lib3ds_file_free(m_model); //free up memory
[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]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
  // 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*2 + i], mesh->texelL[face->points[ i ]], sizeof(Lib3dsTexel));
         memcpy(&vertices[FinishedFaces*3 + i], mesh->pointL[face->points[ i ]].pos, sizeof(Lib3dsVector));

[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]  // 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);[/size][/color][/font]
[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]  // Clean up our allocated memory
  delete vertices;
  delete normals;
  delete texCoords;

  // We no longer need lib3ds
  m_model = NULL;
void Object::applyTexture(const char*texfilename)

  textureObject = SOIL_load_OGL_texture(texfilename,SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID,SOIL_FLAG_MIPMAPS);
    glBindTexture(GL_TEXTURE_2D,textureObject);// use our newest texture
[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]void Object::Draw() const

[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]// Enable vertex, normal and texture-coordinate arrays.
glEnableClientState(GL_TEXTURE_COORD_ARRAY); [/size][/color][/font]

[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]// 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);[/size][/color][/font]
[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]glBindBuffer(GL_ARRAY_BUFFER, m_TexCoordVBO);  
glTexCoordPointer(2, GL_FLOAT, 0,(char *) NULL);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexVBO);
glVertexPointer(3, GL_FLOAT, 0, NULL);
// Render the triangles.
glDrawArrays(GL_TRIANGLES, 0, m_TotalFaces * 3);[/size][/color][/font]

[font="helvetica, arial, verdana, tahoma, sans-serif"][color="#282828"][size=3]glDisableClientState(GL_VERTEX_ARRAY);


the output should actually be a perfectly mapped pyramid with no black parts

1 Reply

Please log in or register to post a reply.

Vilem_Otte 117 Apr 10, 2012 at 00:13

Your code seems wrong.

You once create 3 * sizeof(Lib3dsTexel) - at

Lib3dsTexel* texCoords = new Lib3dsTexel[m_TotalFaces * 3];

Then you copy just 2 * sizeof(Lib3dsTexel) - at

memcpy(&texCoords[FinishedFaces*2 + i], mesh->texelL[face->points[ i ]], sizeof(Lib3dsTexel));

Then you load 3 * sizeof(Lib3dsTexel) to VRAM - definitely should be 2 * sizeof(Lib3dsTexel) - after you copy that array in the way thats shortening it of third dimension - at

glBufferData(GL_ARRAY_BUFFER, sizeof(Lib3dsTexel) * 3 * m_TotalFaces, texCoords, GL_STATIC_DRAW);[/

And then at this 3 * sizeof(Lib3dsTexel) you’re reading 2 coordinates - at

glTexCoordPointer(2, GL_FLOAT, 0,(char *) NULL);

I hope this hint is enough to point you in right way ;) - if you still don’t understand it, I can write further info on this (commenting your code - what it actually does now and what should it do imo) :)