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:
- DevIL.
- GLFW or freeglut for the glut tests.
- Assimp
- C++ compiler
- A windows platform for the last (currently the only successful) test.
- A 3D model supported by assimp, hopefully with some textures and additions.
This is the class which I basically took the code from the assimp "SimpleTexturedOpenGL" sample, and organized it into a class.
The header file
- Create a Mesh object.
- Call the Init() function passing as parameter the name of the 3D model with its file format suffix.
- Call Render() when rendering the OpenGL scene.
Code :#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
Code :#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)
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; 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)
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()); } 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.
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\nYour 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!



