#include #include #include #include "OpenGLController.h" #include "callback.h" #include #include "shader.hpp" #include "Texture.h" #include #define VERTEX_SHADER "Shader/VertexTextureShader.mv2shdr" #define FRAGMENT_SHADER "Shader/FragmentTextureShader.mv2shdr" //#define TEXTURE_NAME "Textures/texture32R.tga" ///////////////////////////////////////////////////////////////////////// // public constructor/destructor OpenGLController* OpenGLController::getInstance(int oglMajor, int oglMinor) { static OpenGLController *instace = new OpenGLController(oglMajor, oglMinor); return instace; } OpenGLController::~OpenGLController() { glDeleteBuffers(1, &gluiUVBufferID); glDeleteBuffers(1, &gluiVertexBufferID); glDeleteVertexArrays(1, &gluiVertexArrayID); glDeleteProgram(gluiShaderPrgmID); glDeleteTextures(1, &gluiSamplerID); glfwTerminate(); while (!vModels.empty()) { Modl* cursor = vModels.back(); vModels.pop_back(); delete cursor->uv; delete cursor->mesh; delete cursor->vertex; delete cursor; } } ///////////////////////////////////////////////////////////////////////// // private constructor OpenGLController::OpenGLController(int oglMajor, int oglMinor) { // init variables initDefault(); iOglMajorVersion = oglMajor; iOglMinorVersion = oglMinor; // run OGL processInit(); } ///////////////////////////////////////////////////////////////////////// // private functions void OpenGLController::initDefault() { pWindow = NULL; sWindowName = "MeshViewer 2.0 pre-alpha"; iWidth = 640; iHeight = 480; iAntiAliasingLevel = 4; gluiUVBufferID = 0; gluiTextureID = 0; gluiShaderPrgmID = 0; gluiSamplerID = 0; gluiMatrixID = 0; fRotationX = 0; fRotationY = 0; fRotationZ = 0; dTranslationX = 0; dTranslationY = 0; dTranslationZ = 5; fFOV = 45.0f; fMinView = 0.1f; fMaxView = 100.0f; } void OpenGLController::processInit() { startGLFW(); createWindow(); startGLEW(); setCallbackFunctions(); // set background color glClearColor(0.5000f, 0.8000f, 1.0000f, 0.0000f); // enable z-order glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // draw vertics only from one side glEnable(GL_CULL_FACE); // generate stuff glGenVertexArrays(1, &gluiVertexArrayID); glBindVertexArray(gluiVertexArrayID); glGenBuffers(1, &gluiVertexBufferID); glGenBuffers(1, &gluiUVBufferID); // get the painter ready try { gluiShaderPrgmID = LoadShaders(VERTEX_SHADER, FRAGMENT_SHADER); } catch (std::invalid_argument e) { MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); exit(1); } gluiMatrixID = glGetUniformLocation(gluiShaderPrgmID, "MVP"); gluiSamplerID = glGetUniformLocation(gluiShaderPrgmID, "textureSampler"); } void OpenGLController::startGLFW() { if (!glfwInit()) { MessageBox(NULL, "Failed to initialize GLFW", "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); exit(0); } glfwWindowHint(GLFW_SAMPLES, iAntiAliasingLevel); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, iOglMajorVersion); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, iOglMinorVersion); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); } void OpenGLController::createWindow() { pWindow = glfwCreateWindow(iWidth, iHeight, sWindowName.c_str(), NULL, NULL); if (pWindow == NULL) { std::string message = "Your GPU does not support OpenGL "; message += iOglMajorVersion; message += "."; message += iOglMinorVersion; message += "\nTry to use older version"; MessageBox(NULL, message.c_str(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); glfwTerminate(); exit(0); } glfwSetWindowUserPointer(pWindow, this); glfwMakeContextCurrent(pWindow); } void OpenGLController::startGLEW() { glewExperimental = true; if (glewInit() != GLEW_OK) { MessageBox(NULL, "Failed to initialize GLEW", "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); glfwTerminate(); exit(0); } } void OpenGLController::setCallbackFunctions() { glfwSetMouseButtonCallback(pWindow, mouseButton); glfwSetCursorPosCallback(pWindow, mouseMove); glfwSetWindowSizeCallback(pWindow, windowResize); glfwSetScrollCallback(pWindow, mouseWheel); glfwSetKeyCallback(pWindow, keyPress); } glm::mat4 OpenGLController::getMVPMatrix() { // Projection glm::mat4 m4x4Projection = glm::perspective(fFOV, float(iWidth) / float(iHeight), fMinView, fMaxView); // View glm::mat4 m4x4View = glm::lookAt( glm::vec3(dTranslationX, dTranslationY, dTranslationZ), glm::vec3(dTranslationX, dTranslationY, dTranslationZ - 1), glm::vec3(0, 1, 0) ); // Model //TODO for all glm::mat4 m4x4Model = vModels.front()->m4x4Translation; // User controlled rotation glm::mat4 m4x4ModelRot = glm::mat4(1.0f); m4x4ModelRot = glm::rotate(m4x4ModelRot, fRotationX, glm::vec3(1, 0, 0)); m4x4ModelRot = glm::rotate(m4x4ModelRot, fRotationY, glm::vec3(0, 1, 0)); m4x4ModelRot = glm::rotate(m4x4ModelRot, fRotationZ, glm::vec3(0, 0, 1)); // Return MVP return m4x4Projection * m4x4View * m4x4ModelRot * m4x4Model; } ///////////////////////////////////////////////////////////////////////// // public getter GLFWwindow * OpenGLController::getWindow() const { return pWindow; } ///////////////////////////////////////////////////////////////////////// // public functions void OpenGLController::resize(int width, int height) { iWidth = width; iHeight = height; } void OpenGLController::addRotX(float value) { fRotationX += value; } void OpenGLController::addRotY(float value) { fRotationY += value; } void OpenGLController::addTransX(double value) { dTranslationX += value; } void OpenGLController::addTransY(double value) { dTranslationY += value; } void OpenGLController::addTransZ(double value) { dTranslationZ += value; } void OpenGLController::updateScene() { // get new matrices glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use shader prgm glUseProgram(gluiShaderPrgmID); // tell shader transformation glUniformMatrix4fv(gluiMatrixID, 1, GL_FALSE, &getMVPMatrix()[0][0]); // bind texture in texture unit 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gluiTextureID); // tell sampler to use texture unit 0 glUniform1i(gluiSamplerID, 0); // open attribute position glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // open attribute uv glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, gluiUVBufferID); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); //draw objects //// TODO: for all glDrawArrays(GL_TRIANGLES, 0, vModels.front()->meshSize); //close attributes glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glfwSwapBuffers(pWindow); glfwPollEvents(); } void OpenGLController::loadMsh(const char * path) { // get data try { Object obj(path); vModels = obj.getModels(); } catch (std::invalid_argument e) { MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); exit(1); } glGenTextures(1, &gluiTextureID); glBindTexture(GL_TEXTURE_2D, gluiTextureID); try { ////TODO: for all if (vModels.front()->texture == "") throw std::invalid_argument("no texture name"); std::string tempPath = path; while (tempPath.back() != '/' && tempPath.back() != '\\') tempPath.pop_back(); TextureTGA tempTex(std::string(tempPath + vModels.front()->texture).c_str()); glTexImage2D(GL_TEXTURE_2D, 0, tempTex.hasAlpha() ? GL_RGBA : GL_RGB, tempTex.getWidth(), tempTex.getHeight(), 0, tempTex.hasAlpha() ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, tempTex.getData().data() ); } catch (std::invalid_argument e) { GLubyte solidColor[4] = { 255, 0, 0, 255}; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)solidColor ); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmap(GL_TEXTURE_2D); glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID); ////TODO: for all std::vector tempVertex; for (unsigned int i = 0; i < vModels.front()->meshSize; i++) { tempVertex.push_back((GLfloat)vModels.front()->vertex[vModels.front()->mesh[i] * 3]); tempVertex.push_back((GLfloat)vModels.front()->vertex[vModels.front()->mesh[i] * 3 + 1]); tempVertex.push_back((GLfloat)vModels.front()->vertex[vModels.front()->mesh[i] * 3 + 2]); } glBufferData( GL_ARRAY_BUFFER, sizeof(tempVertex) * tempVertex.size(), tempVertex.data(), GL_STATIC_DRAW ); ////TODO: for all std::vector tempUV; if (vModels.front()->uv == NULL) { for (unsigned int i = 0; i < vModels.front()->meshSize; i++) tempUV.push_back(1.0); } else { for (unsigned int i = 0; i < vModels.front()->meshSize; i++) { tempUV.push_back((GLfloat)vModels.front()->uv[vModels.front()->mesh[i] * 2]); tempUV.push_back((GLfloat)vModels.front()->uv[vModels.front()->mesh[i] * 2 + 1]); } } glBindBuffer(GL_ARRAY_BUFFER, gluiUVBufferID); glBufferData( GL_ARRAY_BUFFER, sizeof(tempUV) * tempUV.size(), tempUV.data(), GL_STATIC_DRAW ); }