Using assimp with GLUT/GLFW

Hey everyone!
I am trying to write a class that can import models using the assimp library and render them to OpenGL with a call to a function called Render().
I am trying to make the window creation process platform independent so I included the GLFW library, and when that didn’t work I tried the freeglut library which didn’t work either.

To compile this code you will need the following libraries/tools:
[ul]
[li] DevIL.
[/li][li] GLFW or freeglut for the glut tests.
[/li][li] Assimp
[/li][li] C++ compiler
[/li][li] A windows platform for the last (currently the only successful) test.
[/li][li] A 3D model supported by assimp, hopefully with some textures and additions.
[/li][/ul]

This is the class which I basically took the code from the assimp “SimpleTexturedOpenGL” sample, and organized it into a class.

The header file

[ol]
[li]Create a Mesh object.
[/li][li]Call the Init() function passing as parameter the name of the 3D model with its file format suffix.
[/li][li]Call Render() when rendering the OpenGL scene.
[/li][li]
[/li][/ol]


#ifndef MESH_H
#define MESH_H

#include <GL\freeglut.h> //Same as GLFW, but trying glut as an alternative
#include <GL\glut.h>
//#include <GL\glfw.h> //Use GLFW to open a window cross-platform and render with OpenGL

#include <assimp\Importer.hpp>
#include <assimp\postprocess.h>
#include <assimp\scene.h>
#include <IL\il.h>
#include <map>
#include <iostream>

class Mesh
{
	public:
		Mesh();
		Mesh(std::string modelName);
		~Mesh(void);
		void Init(std::string modelName);
		void Render(float scale);
		void ApplyMaterial(const aiMaterial* mat);
		int LoadGLTextures();
	private:
		void Color4f(const aiColor4D* color);
		void Render(const aiNode* node, float scale);
		bool configured;
		const aiScene *scene;
		std::map<std::string, GLuint*> textureIdMap;
		GLuint* textureIds;
		std::string basePath,
					modelName;
		Assimp::Importer modelImporter;		
};

#endif

The class definition


#include "Mesh.h"


Mesh::Mesh()
{
}

Mesh::Mesh(std::string modelName)
{
	Init(modelName);
}


Mesh::~Mesh(void)
{
}

void Mesh::Init(std::string modelName)
{
	basePath = "models/3DS/tank/";   //<--- Base path to where the models are included.
	this->modelName = modelName;
	configured = false;

	scene = modelImporter.ReadFile((basePath + modelName), aiProcessPreset_TargetRealtime_Quality);// If the import failed, report it
	if( !scene)
	{
		std::cout << modelImporter.GetErrorString() << std::endl;
	}
	LoadGLTextures();

}

void Mesh::Render(float scale)
{
	this->Render(scene->mRootNode, scale);
}

void Mesh::Render(const aiNode* node, float scale)
{
	std::cout << "[Rendering]" << std::endl;
	unsigned int i = 0,
				 t = 0,
				 n = 0;
	aiMatrix4x4 aiM = node->mTransformation;
	aiM.Scaling(aiVector3D(scale, scale, scale), aiM);

	aiM.Transpose();
	glPushMatrix();
	glMultMatrixf((float*)&aiM);

	for(; n < node->mNumMeshes; ++n)
	{
		const aiMesh* mesh = scene->mMeshes[node->mMeshes[n]];

		ApplyMaterial(scene->mMaterials[mesh->mMaterialIndex]);

		if(mesh->mNormals == NULL)
		{
			glDisable(GL_LIGHTING);
		}
		else
		{
			glEnable(GL_LIGHTING);
		}

		if(mesh->mColors[0] != NULL)
		{
			glEnable(GL_COLOR_MATERIAL);
		}
		else
		{
			glDisable(GL_COLOR_MATERIAL);
		}

		for(unsigned int t = 0; t < mesh->mNumFaces; ++t)
		{
			const aiFace* face = &mesh->mFaces[t];
			GLenum face_mode;

			switch(face->mNumIndices)
			{
				case 1: 
					face_mode = GL_POINTS;
					break;
				case 2:
					face_mode = GL_LINES;
					break;
				case 3:
					face_mode = GL_TRIANGLES;
					break;
				case 4:
					face_mode = GL_POLYGON;
					break;
			}

			glBegin(face_mode);

			for(unsigned int i = 0; i < face->mNumIndices; ++i)
			{
				int vertexIndex = face->mIndices[i];
				
				if(mesh->mColors[0] != NULL)
				{
					Color4f(&mesh->mColors[0][vertexIndex]);
				}
				if(mesh->mNormals != NULL)
				{
					if(mesh->HasTextureCoords(0))
					{
						glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, 1 - mesh->mTextureCoords[0][vertexIndex].y);
					}
					glNormal3fv(&mesh->mNormals[vertexIndex].x);
				}
				glVertex3fv(&mesh->mVertices[vertexIndex].x);
			}
			
			glEnd();
		}
	}

	// draw all children
	for(unsigned int n = 0; n < node->mNumChildren; ++n)
	{
		this->Render(node->mChildren[n], scale);
	}

	glPopMatrix();
}

void Mesh::ApplyMaterial(const aiMaterial* mat)
{
	float c[4];

	GLenum fillMode;
	unsigned int max = 0;
	int ret1 = 0,
		ret2 = 0,
		twoSided = 0,
		wireframe = 0,
		texIndex = 0;
	aiColor4D diffuse,
			  specular,
			  ambient,
			  emission;
	float shininess = 0.0f,
		  strength = 0.0f;

	aiString texPath;

	if(AI_SUCCESS ==  mat->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
	{
		unsigned int texId = *textureIdMap[texPath.data];
		glBindTexture(GL_TEXTURE_2D, texId);
	}

	c[0] = 0.8f; 
        c[1] = 0.8f; 
        c[2] = 0.8f;
        c[3] = 1.0f;

	if(AI_SUCCESS == aiGetMaterialColor(mat, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
	{
		c[0] = diffuse.r;
		c[1] = diffuse.g;
		c[2] = diffuse.b;
		c[3] = diffuse.a;
	}
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c);

	c[0] = 0.0f;
        c[1] = 0.0f; 
        c[2] = 0.0f; 
        c[3] = 1.0f;

	if(AI_SUCCESS == aiGetMaterialColor(mat, AI_MATKEY_COLOR_SPECULAR, &specular))
	{
		c[0] = specular.r;
		c[1] = specular.g;
		c[2] = specular.b;
		c[3] = specular.a;
	}
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
	
	c[0] = 0.2f; 
        c[1] = 0.2f; 
        c[2] = 0.2f; 
        c[3] = 1.0f;

	if(AI_SUCCESS == aiGetMaterialColor(mat, AI_MATKEY_COLOR_AMBIENT, &ambient))
	{
		c[0] = ambient.r;
		c[1] = ambient.g;
		c[2] = ambient.b;
		c[3] = ambient.a;
	}
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c);
	
	c[0] = 0.0f; 
        c[1] = 0.0f;
        c[2] = 0.0f;
        c[3] = 1.0f;

	if(AI_SUCCESS == aiGetMaterialColor(mat, AI_MATKEY_COLOR_EMISSIVE, &emission))
	{
		c[0] = emission.r;
		c[1] = emission.g;
		c[2] = emission.b;
		c[3] = emission.a;
	}
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c);

	max = 1;
	ret1 = aiGetMaterialFloatArray(mat, AI_MATKEY_SHININESS, &shininess, &max);
	max = 1;
	ret2 = aiGetMaterialFloatArray(mat, AI_MATKEY_SHININESS_STRENGTH, &strength, &max);

	if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS))
	{
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength);
	}
	else
	{
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
		c[0] = 0.0f; 
                c[1] = 0.0f;
                c[2] = 0.0f;
                c[3] = 0.0f;
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
	}

	max = 1;
	if(AI_SUCCESS == aiGetMaterialIntegerArray(mat, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max))
	{
		fillMode = wireframe ? GL_LINE : GL_FILL;
	}
	else
	{
		fillMode = GL_FILL;
	}
	glPolygonMode(GL_FRONT_AND_BACK, fillMode);

	max = 1;
	if((AI_SUCCESS == aiGetMaterialIntegerArray(mat, AI_MATKEY_TWOSIDED, &twoSided, &max)) && twoSided)
	{
		glEnable(GL_CULL_FACE);
	}
	else
	{
		glDisable(GL_CULL_FACE);
	}

}

int Mesh::LoadGLTextures()
{
	ILboolean success;

	if(ilGetInteger(IL_VERSION_NUM) < IL_VERSION)
	{
		ILint test = ilGetInteger(IL_VERSION_NUM);
		//wrong DevIL version
		std::string error = "Wrong DevIL version";
		char* cError = (char*) error.c_str();
		//glfwCloseWindow();
		return -1;
	}

	ilInit();

	if(scene->HasTextures())
	{
		//glfwCloseWindow();
	}

	for(unsigned int i = 0; i < scene->mNumMaterials; ++i)
	{
		int texIndex = 0;
		aiReturn texFound = AI_SUCCESS;
		aiString path; //filename

		while(texFound == AI_SUCCESS)
		{
			texFound = scene->mMaterials[i]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
			textureIdMap[path.data] = NULL;
			texIndex++;
		}
	}

	int numTextures = textureIdMap.size();

	ILuint* imageIds = NULL;
	imageIds = new ILuint[numTextures];

	/* generate DevIL Image IDs */
	ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */

	/* create and fill array with GL texture ids */
	textureIds = new GLuint[numTextures];
	glGenTextures(numTextures, textureIds); /* Texture name generation */

	/* define texture path */
	//std::string texturepath = "../../../test/models/Obj/";

	/* get iterator */
	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();

	for (int i=0; i<numTextures; i++)
	{

		//save IL image ID
		std::string filename = (*itr).first;  // get filename
		(*itr).second =  &textureIds[i];	  // save texture id for filename in map
		itr++;								  // next texture


		ilBindImage(imageIds[i]); /* Binding of DevIL image name */
		std::string fileloc = basePath + filename;	/* Loading of image */
		success = ilLoadImage(fileloc.c_str());

		if (success) /* If no error occured: */
		{
			success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); /* Convert every colour component into
			unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA */
			if (!success)
			{
				/* Error occured */
				std::cout << "Couldn't convert image." << std::endl;
				//glfwCloseWindow();
				return -1;
			}
			//glGenTextures(numTextures, &textureIds[i]); /* Texture name generation */
			glBindTexture(GL_TEXTURE_2D, textureIds[i]); /* Binding of texture name */
			//redefine standard texture values
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* We will use linear
			interpolation for magnification filter */
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* We will use linear
			interpolation for minifying filter */
			glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
				ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE,
				ilGetData()); /* Texture specification */
		}
		else
		{
			/* Error occured */
			std::cout << "Couldn't load image:" << fileloc << std::endl;
			//MessageBox(NULL, ("Couldn't load Image: " + fileloc).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION);
		}


	}

	ilDeleteImages(numTextures, imageIds); /* Because we have already copied image data into texture data
	we can release memory used by image. */

	//Cleanup
	delete [] imageIds;
	imageIds = NULL;

	//return success;
	return true;
}

void Mesh::Color4f(const aiColor4D* color)
{
	glColor4f(color->r, color->g, color->b, color->a);
}

The main.cpp code (GLUT)


#include "Mesh.h"
#include <assimp/DefaultLogger.hpp>
#include <stdlib.h>

void createAILogger()
{
	//Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL;
	Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE;

	// Create a logger instance for Console Output
	Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT);

	// Create a logger instance for File Output (found in project folder or near .exe)
	Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE);

	// Now I am ready for logging my stuff
	Assimp::DefaultLogger::get()->info("this is my info-call");
}

void logInfo(std::string logString)
{
	//Will add message to File with "info" Tag
	Assimp::DefaultLogger::get()->info(logString.c_str());
}

Mesh mesh;

GLfloat		xrot;
GLfloat		yrot;
GLfloat		zrot;

GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f };

int InitGL()					 // All Setup For OpenGL goes here
{

	mesh.Init("M1_Abrams.3DS");

	glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);		 // Enables Smooth Shading
	glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
	glClearDepth(1.0f);				// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);		// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);			// The Type Of Depth Test To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculation


	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);    // Uses default lighting parameters
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
	glEnable(GL_NORMALIZE);

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
	glEnable(GL_LIGHT1);

	glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);


	return true;					// Initialization Went OK
}

void DrawGLScene()				//Here's where we do all the drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();				// Reset MV Matrix

	glTranslatef(0.0f, -10.0f, -40.0f);	// Move 40 Units And Into The Screen


	glRotatef(xrot, 1.0f, 0.0f, 0.0f);
	glRotatef(yrot, 0.0f, 1.0f, 0.0f);
	glRotatef(zrot, 0.0f, 0.0f, 1.0f);

	mesh.Render(0.5f);

	
	glutSwapBuffers();
	//xrot+=0.3f;
	yrot+=0.2f;
	//zrot+=0.4f;
}


void glutDisplayFunction()
{
	DrawGLScene();
}


int main(int argc, char** argv)
{
	bool done = false;	// Bool Variable To Exit Loop
	
	glutInit(&argc,argv);
	
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_STENCIL | GLUT_RGBA);
	glutInitWindowSize(800,600);

	if(!glutCreateWindow("Testing"))
	{
		exit(EXIT_FAILURE);
	}

	glutIdleFunc(&glutDisplayFunction);
	glutDisplayFunc(&glutDisplayFunction);
	
	InitGL(); //Load mesh, call LoadGLTextures and set OpenGL values.

	createAILogger();
	logInfo("App fired!");

	// load scene
	logInfo("=============== Post Import ====================");


	glutMainLoop();
	return 0;
}

That code opens a window and it’s supposed to render the model, but does not render anything, although the model is getting imported and the Render function is being processed.

GLUT was after I tried GLFW.

The main.cpp code (GLFW)


#include "Mesh.h"
#include <assimp/DefaultLogger.hpp>
#include <stdlib.h>

void createAILogger()
{
	//Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL;
	Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE;

	// Create a logger instance for Console Output
	Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT);

	// Create a logger instance for File Output (found in project folder or near .exe)
	Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE);

	// Now I am ready for logging my stuff
	Assimp::DefaultLogger::get()->info("this is my info-call");
}

void logInfo(std::string logString)
{
	//Will add message to File with "info" Tag
	Assimp::DefaultLogger::get()->info(logString.c_str());
}

int main()
{
	int running = GL_TRUE;

	if(!glfwInit())
	{
		exit(EXIT_FAILURE);
	}
	
	if(!glfwOpenWindow(800, 600, 0, 0, 0, 8, 8, 0, GLFW_WINDOW))
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}
	

	glEnable(GL_TEXTURE_2D);
	glClearDepth(1.0f);				// Depth Buffer Setup
	glShadeModel(GL_SMOOTH);		 // Enables Smooth Shading
	glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
	glEnable(GL_DEPTH_TEST);		// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);			// The Type Of Depth Test To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculation


	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);    // Uses default lighting parameters
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
	glEnable(GL_NORMALIZE);
	GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f };
	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
	glEnable(GL_LIGHT1);
	GLfloat		xrot;
GLfloat		yrot;
GLfloat		zrot;

	Mesh mesh;     
        mesh.Init("M1_Abrams.3DS"); // <--- Import and initialize the model

	createAILogger();
	logInfo("Post import.");

		//glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 );
	while(running)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glTranslatef(0.0f, -10.0f, -40.0f);	// Move 40 Units And Into The Screen


		glRotatef(xrot, 1.0f, 0.0f, 0.0f);
		glRotatef(yrot, 0.0f, 1.0f, 0.0f);
		glRotatef(zrot, 0.0f, 0.0f, 1.0f);
                mesh.Render(0.5f);                 // This is where the mesh tries to render to OpenGL.
		yrot+=0.2f;
		glfwSwapBuffers();
		running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);
	}
	glfwTerminate();

	exit(EXIT_SUCCESS);
}

With this happens the same thing as with glut, the window opens but the model does not show on the screen.

I was pretty sure that code worked because it works in the assimp sample. Next thing I tried was rendering the window using the same code as the sample. I don’t like that because it’s Windows dependent code.


#include "Mesh.h"
#include <assimp/DefaultLogger.hpp>
#include <stdlib.h>

void createAILogger()
{
	//Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL;
	Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE;

	// Create a logger instance for Console Output
	Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT);

	// Create a logger instance for File Output (found in project folder or near .exe)
	Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE);

	// Now I am ready for logging my stuff
	Assimp::DefaultLogger::get()->info("this is my info-call");
}

void logInfo(std::string logString)
{
	//Will add message to File with "info" Tag
	Assimp::DefaultLogger::get()->info(logString.c_str());
}

Mesh mesh;   // <---The Mesh class - Woo!
HGLRC		hRC=NULL;			// Permanent Rendering Context
HDC			hDC=NULL;			// Private GDI Device Context
HWND		hWnd=NULL;			// Holds Window Handle
HINSTANCE	hInstance;	// Holds The Instance Of The Application

bool		keys[256];			// Array used for Keyboard Routine;
bool		active=TRUE;		// Window Active Flag Set To TRUE by Default
bool		fullscreen=TRUE;	// Fullscreen Flag Set To Fullscreen By Default

GLfloat		xrot;
GLfloat		yrot;
GLfloat		zrot;


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	// Declaration For WndProc

const char* windowTitle = "OpenGL Framework";

GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f };

void ReSizeGLScene(GLsizei width, GLsizei height)				// Resize And Initialize The GL Window
{
	if (height==0)								// Prevent A Divide By Zero By
	{
		height=1;							// Making Height Equal One
	}

	glViewport(0, 0, width, height);					// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();							// Reset The Projection Matrix

	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

	glMatrixMode(GL_MODELVIEW);						// Select The Modelview Matrix
	glLoadIdentity();							// Reset The Modelview Matrix
}

int InitGL()					 // All Setup For OpenGL goes here
{
	mesh.LoadGLTextures(); // <-- I know this repeats itself, but the addition to the Init function calling LoadGLTextures was added after this test.


	glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);		 // Enables Smooth Shading
	glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
	glClearDepth(1.0f);				// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);		// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);			// The Type Of Depth Test To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculation


	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);    // Uses default lighting parameters
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
	glEnable(GL_NORMALIZE);

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
	glEnable(GL_LIGHT1);

	//glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);


	return TRUE;					// Initialization Went OK
}

int DrawGLScene()				//Here's where we do all the drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
	glLoadIdentity();				// Reset MV Matrix


	glTranslatef(0.0f, -10.0f, -40.0f);	// Move 40 Units And Into The Screen


	glRotatef(xrot, 1.0f, 0.0f, 0.0f);
	glRotatef(yrot, 0.0f, 1.0f, 0.0f);
	glRotatef(zrot, 0.0f, 0.0f, 1.0f);

	mesh.Render(0.5f);


	//xrot+=0.3f;
	yrot+=0.2f;
	//zrot+=0.4f;

	return TRUE;					// Ewwrissing okay
}

void KillGLWindow()			// Properly Kill The Window
{
	if (fullscreen)					// Are We In Fullscreen Mode?
	{
		ChangeDisplaySettings(NULL, 0);		// If So Switch Back To The Desktop
		ShowCursor(TRUE);					// Show Mouse Pointer
	}

	if (hRC)					// Do We Have A Rendering Context?
	{
		if (!wglMakeCurrent(NULL, NULL))	// Are We Able To Release The DC And RC Contexts?
		{
			MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
		}

		if (!wglDeleteContext(hRC))			// Are We Able To Delete The RC?
		{
			MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
		}
		hRC = NULL;
	}

	if (hDC && !ReleaseDC(hWnd, hDC))	// Are We able to Release The DC?
	{
		MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
		hDC=NULL;
	}

	if (hWnd && !DestroyWindow(hWnd))	// Are We Able To Destroy The Window
	{
		MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
		hWnd = NULL;
	}

	if (!UnregisterClass("OpenGL", hInstance))	// Are We Able To Unregister Class
	{
		MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
		hInstance = NULL;
	}
}

GLboolean abortGLInit(const char* abortMessage)
{
	KillGLWindow();									// Reset Display
	MessageBox(NULL, abortMessage, "ERROR", MB_OK|MB_ICONEXCLAMATION);
	return FALSE;									// quit and return False
}

BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool fullscreenflag)
{
	GLuint		PixelFormat;		// Hold the result after searching for a match
	WNDCLASS	wc;					// Window Class Structure
	DWORD		dwExStyle;			// Window Extended Style
	DWORD		dwStyle;			// Window Style
	RECT		WindowRect;			// Grabs Rectangle Upper Left / Lower Right Values
	WindowRect.left		= (long)0;
	WindowRect.right	= (long)width;
	WindowRect.top		= (long)0;
	WindowRect.bottom	= (long)height;

	fullscreen = fullscreenflag;

	hInstance = GetModuleHandle(NULL);	// Grab An Instance For Our Window
	wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window
	wc.lpfnWndProc	= (WNDPROC) WndProc;		// WndProc handles Messages
	wc.cbClsExtra	= 0;	// No Extra Window Data
	wc.cbWndExtra	= 0;	// No Extra Window Data
	wc.hInstance	= hInstance;
	wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);	// Load The Default Icon
	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);	// Load the default arrow
	wc.hbrBackground= NULL;							// No Background required for OpenGL
	wc.lpszMenuName	= NULL;							// No Menu
	wc.lpszClassName= "OpenGL";						// Class Name

	if (!RegisterClass(&wc))
	{
		MessageBox(NULL, "Failed to register the window class", "ERROR", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;		//exit and return false
	}

	if (fullscreen)		// attempt fullscreen mode
	{
		DEVMODE dmScreenSettings;								// Device Mode
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));	// Make Sure Memory's Cleared
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);		// Size Of the devmode structure
		dmScreenSettings.dmPelsWidth	= width;				// Selected Screen Width
		dmScreenSettings.dmPelsHeight	= height;				// Selected Screen Height
		dmScreenSettings.dmBitsPerPel	= bits;					// bits per pixel
		dmScreenSettings.dmFields		= DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

		// Try To Set Selected Mode and Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
		{
			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
			if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By
Your Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
			{
				fullscreen = FALSE;		// Select Windowed Mode (Fullscreen = FALSE)
			}
			else
			{
				//Popup Messagebox: Closing
				MessageBox(NULL, "Program will close now.", "ERROR", MB_OK|MB_ICONSTOP);
				return FALSE; //exit, return false
			}
		}
	}

	if (fullscreen)		// when mode really succeeded
	{
		dwExStyle=WS_EX_APPWINDOW;		// Window Extended Style
		dwStyle=WS_POPUP;
		ShowCursor(FALSE);
	}
	else
	{
		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;	// Window extended style
		dwStyle=WS_OVERLAPPEDWINDOW;					// Windows style
	}

	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requestes Size

	if (!(hWnd=CreateWindowEx(	dwExStyle,						// Extended Style For The Window
								"OpenGL",						// Class Name
								title,							// Window Title
								WS_CLIPSIBLINGS |				// Required Window Style
								WS_CLIPCHILDREN |				// Required Window Style
								dwStyle,						// Selected WIndow Style
								0, 0,							// Window Position
								WindowRect.right-WindowRect.left, // Calc adjusted Window Width
								WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height
								NULL,							// No Parent Window
								NULL,							// No Menu
								hInstance,						// Instance
								NULL )))						// Don't pass anything To WM_CREATE
	{
		abortGLInit("Window Creation Error.");
		return FALSE;
		
		KillGLWindow();											// Reset The Display
		MessageBox(NULL, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// Return False
		
	}
	
	
	static	PIXELFORMATDESCRIPTOR pfd=					// pfd Tells Windows How We Want Things To Be
	{
		sizeof(PIXELFORMATDESCRIPTOR),					// Size Of This Pixel Format Descriptor
		1,												// Version Number
		PFD_DRAW_TO_WINDOW |							// Format Must Support Window
		PFD_SUPPORT_OPENGL |							// Format Must Support OpenGL
		PFD_DOUBLEBUFFER,								// Must Support Double Buffering
		PFD_TYPE_RGBA,									// Request An RGBA Format
		bits,											// Select Our Color Depth
		0, 0, 0, 0, 0, 0,								// Color Bits Ignored
		0,												// No Alpha Buffer
		0,												// Shift Bit Ignored
		0,												// No Accumulation Buffer
		0, 0, 0, 0,										// Accumulation Bits Ignored
		16,												// 16Bit Z-Buffer (Depth Buffer)
		0,												// No Stencil Buffer
		0,												// No Auxiliary Buffer
		PFD_MAIN_PLANE,									// Main Drawing Layer
		0,												// Reserved
		0, 0, 0											// Layer Masks Ignored
	};

	if (!(hDC=GetDC(hWnd)))								// Did we get the Device Context?
	{
		abortGLInit("Can't Create A GL Device Context.");
		return FALSE;
	}

	if (!(PixelFormat=ChoosePixelFormat(hDC, &pfd)))	// Did We Find a matching pixel Format?
	{
		abortGLInit("Can't Find Suitable PixelFormat");
		return FALSE;
	}

	if (!SetPixelFormat(hDC, PixelFormat, &pfd))
	{
		abortGLInit("Can't Set The PixelFormat");
		return FALSE;
	}

	if (!(hRC=wglCreateContext(hDC)))
	{
		abortGLInit("Can't Create A GL Rendering Context.");
		return FALSE;
	}

	if (!(wglMakeCurrent(hDC,hRC)))						// Try to activate the rendering context
	{
		abortGLInit("Can't Activate The Rendering Context");
		return FALSE;
	}

	//// *** everything okay ***

	ShowWindow(hWnd, SW_SHOW);		// Show The Window
	SetForegroundWindow(hWnd);		// Slightly Higher Prio
	SetFocus(hWnd);					// Sets Keyboard Focus To The Window
	ReSizeGLScene(width, height);	// Set Up Our Perspective GL Screen

	if (!InitGL())
	{
		abortGLInit("Initialization failed");
		return FALSE;
	}

	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
						 UINT uMsg,				// Message for this Window
						 WPARAM wParam,			// additional message Info
						 LPARAM lParam)			// additional message Info
{
	switch (uMsg)				// check for Window Messages
	{
		case WM_ACTIVATE:				// Watch For Window Activate Message
			{
				if (!HIWORD(wParam))	// Check Minimization State
				{
					active=TRUE;
				}
				else
				{
					active=FALSE;
				}

				return 0;				// return To The Message Loop
			}

		case WM_SYSCOMMAND:			// Interrupt System Commands
			{
				switch (wParam)
				{
					case SC_SCREENSAVE:		// Screensaver trying to start
					case SC_MONITORPOWER:	// Monitor tryig to enter powersafe
					return 0;
				}
				break;
			}

		case WM_CLOSE:			// close message received?
			{
				PostQuitMessage(0);	// Send WM_QUIT quit message
				return 0;			// Jump Back
			}

		case WM_KEYDOWN:		// Is a key pressed?
			{
				keys[wParam] = TRUE;	// If so, Mark it as true
				return 0;
			}

		case WM_KEYUP:			// Has Key Been released?
			{
				keys[wParam] = FALSE;	// If so, Mark It As FALSE
				return 0;
			}

		case WM_SIZE:			// Resize The OpenGL Window
			{
				ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));	// LoWord-Width, HiWord-Height
				return 0;
			}
	}

	// Pass All Unhandled Messaged To DefWindowProc
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


int WINAPI WinMain( HINSTANCE hInstance, // Instance
				   HINSTANCE hPrevInstance,      // Previous Instance
				   LPSTR lpCmdLine,              // Command Line Parameters
				   int nShowCmd )                // Window Show State
{
	MSG msg;			// Windows Message Structure
	BOOL done=FALSE;	// Bool Variable To Exit Loop

	createAILogger();
	logInfo("App fired!");

	// load scene

	mesh.Init("M1_Abrams.3DS");

	logInfo("=============== Post Import ====================");


	// Ask The User Which Screen Mode They Prefer
	if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
	{
		fullscreen=FALSE;		// Windowed Mode
	}

	// Create Our OpenGL Window (also calls GLinit und LoadGLTextures)
	if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
	{
		return 0;
	}




	while(!done)	// Game Loop
	{
		if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE))	// Is There A Message Waiting
		{
			if (msg.message==WM_QUIT)			// Have we received A Quit Message?
			{
				done=TRUE;						// If So done=TRUE
			}
			else
			{
				TranslateMessage(&msg);			// Translate The Message
				DispatchMessage(&msg);			// Dispatch The Message
			}
		}
		else
		{
			// Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene()
			if (active)
			{
				if (keys[VK_ESCAPE])	// Was ESC pressed?
				{
					done=TRUE;			// ESC signalled A quit
				}
				else
				{
					DrawGLScene();		// Draw The Scene
					SwapBuffers(hDC);	// Swap Buffers (Double Buffering)
				}
			}

			if (keys[VK_F1])		// Is F1 Being Pressed?
			{
				keys[VK_F1]=FALSE;	// If so make Key FALSE
				KillGLWindow();		// Kill Our Current Window
				fullscreen=!fullscreen;	// Toggle Fullscreen
				//recreate Our OpenGL Window
				if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
				{
					return 0;		// Quit if Window Was Not Created
				}
			}
		}
	}

	// Shutdown
	KillGLWindow();
	return (msg.wParam);	// Exit The Program
}

For reasons that I do not yet understand this last main works like a charm. It renders the model and applies all textures/materials to it.
I have looked into several pages of the forum and other tutorials like lighthouse3D. But some of them use a different procedure than the samples use or they do not answer my questions.

Any insight/advice/suggestion is more than welcome. Thanks!