Skip to content
Snippets Groups Projects
Select Git revision
  • 9c12598bf5710330cafc21456249ba34ffe25b9b
  • master default protected
  • developement_1 protected
  • Version_1.2.4
  • Version_1.2.3
  • Version_1.2.2
  • Version_1.2.1
  • Version_1.2.0
  • Version_1.0.1
  • Version_1.0.0
  • Version_0.1.0
  • Version_0.0.6
  • Version_0.0.5
  • Version_0.0.4
  • Version_0.0.3
  • Version_0.0.2
  • Version_0.0.1
17 results

OpenGlController.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    OpenGlController.cpp 9.18 KiB
    #include <gl\glew.h>
    #include <gl\glfw3.h>
    #include <Windows.h>
    #include "OpenGLController.h"
    #include "callback.h"
    
    #include <glm\gtc\matrix_transform.hpp>
    #include "shader.hpp"
    #include "Texture.h"
    #include <iostream>
    
    #define VERTEX_SHADER "Shader/TextureShader.vert"
    #define FRAGMENT_SHADER "Shader/TextureShader.frag"
    
    
    /////////////////////////////////////////////////////////////////////////
    // public constructor/destructor
    
    OpenGLController* OpenGLController::getInstance(int oglMajor, int oglMinor)
    {
    	static OpenGLController *instace = new OpenGLController(oglMajor, oglMinor);
    	return instace;
    }
    
    OpenGLController::~OpenGLController()
    {
    	glDeleteBuffers(1, &gluiInstanceBufferID);
    	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)
    {
    	// adjust ogl version optional
    	iOglMajorVersion = oglMajor;
    	iOglMinorVersion = oglMinor;
    
    	// run OGL
    	processInit();
    }
    
    /////////////////////////////////////////////////////////////////////////
    // private functions
    
    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, &gluiInstanceBufferID);
    
    	// open attribute position
    	glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID);
    	glVertexAttribPointer(VERTEX_INDEX_XYZ, VERTEX_COMPONENTS_XYZ, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)VERTEX_OFFSET_XYZ);
    	glVertexAttribPointer(VERTEX_INDEX_UV, VERTEX_COMPONENTS_UV, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)VERTEX_OFFSET_UV);
    	glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    	glBindBuffer(GL_ARRAY_BUFFER, gluiInstanceBufferID);
    	glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GL_FLOAT) * 0));
    	glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GL_FLOAT) * 4));
    	glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GL_FLOAT) * 8));
    	glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GL_FLOAT) * 12));
    	glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    	glEnableVertexAttribArray(0);
    	glEnableVertexAttribArray(1);
    
    	// 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 += std::to_string(iOglMajorVersion);
    		message += ".";
    		message += std::to_string(iOglMinorVersion);
    		message += "\nTry to use an other 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]);
    	glBindBuffer(GL_UNIFORM_BUFFER, gluiInstanceBufferID);
    	glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 1, NULL, GL_STREAM_DRAW);
    	glBindBuffer(GL_UNIFORM_BUFFER, 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);
    
    	//draw objects
    	glDrawArrays(GL_TRIANGLES, 0, vModels.front()->meshSize);
    
    	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);
    
    	////TODO: for all
    	std::vector<Vertex> tempBufferData;
    
    	for (unsigned int i = 0; i < vModels.front()->meshSize; i++)
    	{
    		Vertex tempVertex;
    		tempVertex.position[0] = (GLfloat)vModels.front()->vertex[vModels.front()->mesh[i] * 3];
    		tempVertex.position[1] = (GLfloat)vModels.front()->vertex[vModels.front()->mesh[i] * 3 + 1];
    		tempVertex.position[2] = (GLfloat)vModels.front()->vertex[vModels.front()->mesh[i] * 3 + 2];
    
    		if (vModels.front()->uv == NULL)
    		{
    			tempVertex.uv[0] = 1.0;
    			tempVertex.uv[1] = 1.0;
    		}
    		else
    		{
    			tempVertex.uv[0] = (GLfloat)vModels.front()->uv[vModels.front()->mesh[i] * 2];
    			tempVertex.uv[1] = (GLfloat)vModels.front()->uv[vModels.front()->mesh[i] * 2 + 1];
    		}
    
    		tempBufferData.push_back(tempVertex);
    	}
    
    	glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID);
    	glBufferData(
    		GL_ARRAY_BUFFER,
    		sizeof(Vertex) * tempBufferData.size(),
    		tempBufferData.data(),
    		GL_STATIC_DRAW
    	);
    }