I'm using Lib3ds to load 3ds models.
Here is how it creates display list for mesh.
glNewList(mesh->user.d, GL_COMPILE);
Lib3dsVector *normalL=(Lib3dsVector *)malloc(3*sizeof(Lib3dsVector)*mesh->faces);
Lib3dsMaterial *oldmat = (Lib3dsMaterial *)-1;
Lib3dsMatrix M;
lib3ds_matrix_copy(M, mesh->matrix);
lib3ds_matrix_inv(M);
glMultMatrixf(&M[0][0]);
lib3ds_mesh_calculate_normals(mesh, normalL);
glBegin(GL_TRIANGLES);
for (int j=0; j<mesh->faces; ++j)
{
Lib3dsFace *f=&mesh->faceL[j];
Lib3dsMaterial *mat=0;
int tex_mode = 0;
if (f->material[0]) mat=lib3ds_file_material_by_name(file, f->material);
if( mat != oldmat )
{
if (mat)
{
if (mat->two_sided) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE);
if (mat->use_wire ) glEnable(GL_ALPHA_TEST); else glDisable(GL_ALPHA_TEST);
}
oldmat = mat;
}
int i;
if (f->user.i>0)
{
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,f->user.i);
}
glNormal3fv(f->normal);
for (i=0; i<3; ++i)
{
glNormal3fv(normalL[3*j+i]);
float scale=1;
if (mesh->texels>0)
{
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,mesh->texelL[f->points[i]][0]*scale, mesh->texelL[f->points[i]][1]*scale);
}
glVertex3fv(mesh->pointL[f->points[i]].pos);
}
}
glEnd();
free(normalL);
glEndList();