2016-09-06 13:15:29 +00:00
|
|
|
#include <gl\glew.h>
|
|
|
|
#include <gl\glfw3.h>
|
|
|
|
#include <Windows.h>
|
|
|
|
#include "OpenGLController.h"
|
|
|
|
#include "callback.h"
|
|
|
|
|
2016-09-07 14:07:56 +00:00
|
|
|
#include <glm\gtc\matrix_transform.hpp>
|
|
|
|
#include "shader.hpp"
|
|
|
|
#include "Texture.h"
|
2016-10-31 15:19:12 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
2016-11-03 18:46:36 +00:00
|
|
|
#define VERTEX_SHADER "Shader/TextureShader.vert"
|
|
|
|
#define FRAGMENT_SHADER "Shader/TextureShader.frag"
|
2016-11-05 12:36:28 +00:00
|
|
|
#define MAX_MODEL_COUNT 1000
|
2016-09-06 13:15:29 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// public constructor/destructor
|
|
|
|
|
2016-09-08 09:36:57 +00:00
|
|
|
OpenGLController* OpenGLController::getInstance(int oglMajor, int oglMinor)
|
2016-09-06 13:15:29 +00:00
|
|
|
{
|
2016-09-08 09:36:57 +00:00
|
|
|
static OpenGLController *instace = new OpenGLController(oglMajor, oglMinor);
|
2016-09-07 10:46:34 +00:00
|
|
|
return instace;
|
|
|
|
}
|
|
|
|
|
|
|
|
OpenGLController::~OpenGLController()
|
|
|
|
{
|
2016-09-08 09:30:00 +00:00
|
|
|
glDeleteBuffers(1, &gluiVertexBufferID);
|
|
|
|
glDeleteVertexArrays(1, &gluiVertexArrayID);
|
|
|
|
glDeleteProgram(gluiShaderPrgmID);
|
|
|
|
|
2016-09-07 10:46:34 +00:00
|
|
|
glDeleteTextures(1, &gluiSamplerID);
|
|
|
|
glfwTerminate();
|
2016-10-31 15:19:12 +00:00
|
|
|
|
|
|
|
while (!vModels.empty())
|
|
|
|
{
|
|
|
|
Modl* cursor = vModels.back();
|
|
|
|
vModels.pop_back();
|
|
|
|
|
|
|
|
delete cursor->uv;
|
|
|
|
delete cursor->mesh;
|
|
|
|
delete cursor->vertex;
|
|
|
|
delete cursor;
|
|
|
|
}
|
2016-11-08 15:42:05 +00:00
|
|
|
|
|
|
|
while (!vTextures.empty())
|
|
|
|
{
|
|
|
|
textureData* cursor = vTextures.back();
|
|
|
|
vTextures.pop_back();
|
2016-11-08 16:06:50 +00:00
|
|
|
delete cursor->data;
|
2016-11-08 15:42:05 +00:00
|
|
|
delete cursor;
|
|
|
|
}
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
2016-09-07 10:46:34 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// private constructor
|
|
|
|
|
2016-09-07 14:07:56 +00:00
|
|
|
OpenGLController::OpenGLController(int oglMajor, int oglMinor)
|
2016-09-06 13:15:29 +00:00
|
|
|
{
|
2016-11-01 13:16:18 +00:00
|
|
|
// adjust ogl version optional
|
2016-09-06 13:15:29 +00:00
|
|
|
iOglMajorVersion = oglMajor;
|
|
|
|
iOglMinorVersion = oglMinor;
|
2016-09-07 14:07:56 +00:00
|
|
|
|
|
|
|
// run OGL
|
2016-09-06 13:15:29 +00:00
|
|
|
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);
|
2016-10-31 15:19:12 +00:00
|
|
|
|
|
|
|
// generate stuff
|
|
|
|
glGenVertexArrays(1, &gluiVertexArrayID);
|
|
|
|
glBindVertexArray(gluiVertexArrayID);
|
|
|
|
|
|
|
|
glGenBuffers(1, &gluiVertexBufferID);
|
2016-11-01 10:51:04 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2016-11-05 10:53:49 +00:00
|
|
|
// enable position, UV and mvp
|
2016-11-01 10:51:04 +00:00
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
glEnableVertexAttribArray(1);
|
2016-10-31 15:19:12 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2016-11-08 15:42:05 +00:00
|
|
|
// get some shader IDs
|
2016-10-31 15:19:12 +00:00
|
|
|
gluiMatrixID = glGetUniformLocation(gluiShaderPrgmID, "MVP");
|
|
|
|
gluiSamplerID = glGetUniformLocation(gluiShaderPrgmID, "textureSampler");
|
2016-11-08 15:42:05 +00:00
|
|
|
|
|
|
|
// generate texture
|
|
|
|
glGenTextures(1, &gluiTextureID);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, gluiTextureID);
|
2016-11-08 20:28:24 +00:00
|
|
|
|
|
|
|
// set some texture parameters
|
|
|
|
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);
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ";
|
2016-11-01 13:16:18 +00:00
|
|
|
message += std::to_string(iOglMajorVersion);
|
2016-09-06 13:15:29 +00:00
|
|
|
message += ".";
|
2016-11-01 13:16:18 +00:00
|
|
|
message += std::to_string(iOglMinorVersion);
|
|
|
|
message += "\nTry to use an other version";
|
2016-09-06 13:15:29 +00:00
|
|
|
|
|
|
|
MessageBox(NULL, message.c_str(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
|
|
|
|
|
|
|
|
glfwTerminate();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
glfwSetWindowUserPointer(pWindow, this);
|
|
|
|
glfwMakeContextCurrent(pWindow);
|
|
|
|
}
|
|
|
|
|
2016-09-07 14:07:56 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-06 13:15:29 +00:00
|
|
|
void OpenGLController::setCallbackFunctions()
|
|
|
|
{
|
|
|
|
glfwSetMouseButtonCallback(pWindow, mouseButton);
|
|
|
|
glfwSetCursorPosCallback(pWindow, mouseMove);
|
|
|
|
glfwSetWindowSizeCallback(pWindow, windowResize);
|
|
|
|
glfwSetScrollCallback(pWindow, mouseWheel);
|
|
|
|
glfwSetKeyCallback(pWindow, keyPress);
|
|
|
|
}
|
|
|
|
|
2016-11-12 10:54:44 +00:00
|
|
|
glm::mat4 OpenGLController::getModelMatrix(unsigned int index)
|
|
|
|
{
|
|
|
|
glm::mat4 tempParentMatrix = glm::mat4(1.0f);
|
|
|
|
|
|
|
|
for (unsigned int loop = 0; loop < vModels.size(); loop++)
|
|
|
|
{
|
|
|
|
if (!strcmp(vModels[index]->parent.c_str(), vModels[loop]->name.c_str()))
|
|
|
|
{
|
|
|
|
tempParentMatrix = getModelMatrix(loop);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tempParentMatrix * vModels[index]->m4x4Translation;
|
|
|
|
}
|
|
|
|
|
2016-11-07 11:06:55 +00:00
|
|
|
glm::mat4 OpenGLController::getMVPMatrix(unsigned int index)
|
2016-09-06 13:15:29 +00:00
|
|
|
{
|
2016-10-31 09:46:41 +00:00
|
|
|
// Projection
|
|
|
|
glm::mat4 m4x4Projection = glm::perspective(fFOV, float(iWidth) / float(iHeight), fMinView, fMaxView);
|
|
|
|
|
|
|
|
// View
|
|
|
|
glm::mat4 m4x4View = glm::lookAt(
|
2016-09-07 14:07:56 +00:00
|
|
|
glm::vec3(dTranslationX, dTranslationY, dTranslationZ),
|
|
|
|
glm::vec3(dTranslationX, dTranslationY, dTranslationZ - 1),
|
|
|
|
glm::vec3(0, 1, 0)
|
|
|
|
);
|
2016-10-30 13:22:08 +00:00
|
|
|
|
2016-10-31 09:46:41 +00:00
|
|
|
// 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
|
2016-11-12 10:54:44 +00:00
|
|
|
return m4x4Projection * m4x4View * m4x4ModelRot * getModelMatrix(index);
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
2016-09-07 15:17:17 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// public getter
|
|
|
|
|
2016-09-06 13:15:29 +00:00
|
|
|
GLFWwindow * OpenGLController::getWindow() const
|
|
|
|
{
|
|
|
|
return pWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// public functions
|
|
|
|
|
|
|
|
void OpenGLController::resize(int width, int height)
|
|
|
|
{
|
2016-09-07 14:07:56 +00:00
|
|
|
iWidth = width;
|
|
|
|
iHeight = height;
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::addRotX(float value)
|
|
|
|
{
|
2016-09-07 14:07:56 +00:00
|
|
|
fRotationX += value;
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::addRotY(float value)
|
|
|
|
{
|
2016-09-07 14:07:56 +00:00
|
|
|
fRotationY += value;
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::addTransX(double value)
|
|
|
|
{
|
2016-09-07 14:07:56 +00:00
|
|
|
dTranslationX += value;
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::addTransY(double value)
|
|
|
|
{
|
2016-09-07 14:07:56 +00:00
|
|
|
dTranslationY += value;
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::addTransZ(double value)
|
|
|
|
{
|
2016-09-07 14:07:56 +00:00
|
|
|
dTranslationZ += value;
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::updateScene()
|
|
|
|
{
|
|
|
|
// get new matrices
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
// use shader prgm
|
2016-09-07 14:07:56 +00:00
|
|
|
glUseProgram(gluiShaderPrgmID);
|
2016-09-06 13:15:29 +00:00
|
|
|
|
|
|
|
// bind texture in texture unit 0
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
2016-09-07 14:07:56 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, gluiTextureID);
|
2016-09-06 13:15:29 +00:00
|
|
|
// tell sampler to use texture unit 0
|
|
|
|
glUniform1i(gluiSamplerID, 0);
|
|
|
|
|
2016-11-07 11:06:55 +00:00
|
|
|
int instanceOffset(0);
|
|
|
|
|
2016-11-07 16:07:16 +00:00
|
|
|
for (int modelIndex = 0; modelIndex < vModels.size(); modelIndex++)
|
2016-11-07 11:06:55 +00:00
|
|
|
{
|
2016-11-08 20:28:24 +00:00
|
|
|
// give texture to the shader
|
|
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
|
|
0,
|
|
|
|
vTextures[modelIndex]->alpha ? GL_RGBA : GL_RGB,
|
|
|
|
vTextures[modelIndex]->width,
|
|
|
|
vTextures[modelIndex]->height,
|
|
|
|
0,
|
|
|
|
vTextures[modelIndex]->alpha ? GL_BGRA : GL_BGR,
|
|
|
|
GL_UNSIGNED_BYTE,
|
|
|
|
vTextures[modelIndex]->data->data()
|
|
|
|
);
|
|
|
|
|
|
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
// give the MVP to the shader
|
2016-11-07 16:07:16 +00:00
|
|
|
glUniformMatrix4fv(gluiMatrixID, 1, GL_FALSE, &getMVPMatrix(modelIndex)[0][0]);
|
2016-11-07 11:06:55 +00:00
|
|
|
|
2016-11-07 16:07:16 +00:00
|
|
|
glDrawArrays(GL_TRIANGLES, instanceOffset, vModels[modelIndex]->meshSize);
|
2016-11-07 11:06:55 +00:00
|
|
|
|
|
|
|
instanceOffset += vModels[modelIndex]->meshSize;
|
|
|
|
}
|
2016-09-06 13:15:29 +00:00
|
|
|
|
2016-09-07 14:07:56 +00:00
|
|
|
glfwSwapBuffers(pWindow);
|
|
|
|
glfwPollEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLController::loadMsh(const char * path)
|
|
|
|
{
|
2016-11-08 15:42:05 +00:00
|
|
|
// get all models
|
2016-10-16 10:33:25 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
Object obj(path);
|
2016-10-30 13:22:08 +00:00
|
|
|
vModels = obj.getModels();
|
2016-10-16 10:33:25 +00:00
|
|
|
}
|
|
|
|
catch (std::invalid_argument e)
|
|
|
|
{
|
|
|
|
MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-11-08 15:42:05 +00:00
|
|
|
// collect vertex data of all models
|
2016-11-01 10:51:04 +00:00
|
|
|
std::vector<Vertex> tempBufferData;
|
2016-11-08 15:42:05 +00:00
|
|
|
|
2016-11-07 16:07:16 +00:00
|
|
|
for (auto& it : vModels)
|
2016-10-30 13:22:08 +00:00
|
|
|
{
|
2016-11-07 16:07:16 +00:00
|
|
|
for (unsigned int i = 0; i < it->meshSize; i++)
|
2016-10-30 13:22:08 +00:00
|
|
|
{
|
2016-11-07 16:07:16 +00:00
|
|
|
Vertex tempVertex;
|
|
|
|
tempVertex.position[0] = (GLfloat)it->vertex[it->mesh[i] * 3];
|
|
|
|
tempVertex.position[1] = (GLfloat)it->vertex[it->mesh[i] * 3 + 1];
|
|
|
|
tempVertex.position[2] = (GLfloat)it->vertex[it->mesh[i] * 3 + 2];
|
|
|
|
|
|
|
|
if (it->uv == NULL)
|
|
|
|
{
|
|
|
|
tempVertex.uv[0] = 1.0;
|
|
|
|
tempVertex.uv[1] = 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tempVertex.uv[0] = (GLfloat)it->uv[it->mesh[i] * 2];
|
|
|
|
tempVertex.uv[1] = (GLfloat)it->uv[it->mesh[i] * 2 + 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
tempBufferData.push_back(tempVertex);
|
2016-10-30 13:22:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-08 15:42:05 +00:00
|
|
|
// fill the buffer
|
2016-11-01 10:51:04 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID);
|
2016-09-07 14:07:56 +00:00
|
|
|
glBufferData(
|
|
|
|
GL_ARRAY_BUFFER,
|
2016-11-01 16:07:07 +00:00
|
|
|
sizeof(Vertex) * tempBufferData.size(),
|
2016-11-01 10:51:04 +00:00
|
|
|
tempBufferData.data(),
|
2016-09-07 14:07:56 +00:00
|
|
|
GL_STATIC_DRAW
|
|
|
|
);
|
2016-11-07 15:00:57 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
2016-11-07 11:16:39 +00:00
|
|
|
|
2016-11-08 15:42:05 +00:00
|
|
|
|
|
|
|
// get textures
|
|
|
|
for (auto& it : vModels)
|
|
|
|
{
|
|
|
|
textureData* tempData = new textureData;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (it->texture == "")
|
|
|
|
throw std::invalid_argument("no texture name");
|
|
|
|
|
|
|
|
std::string tempPath = path;
|
|
|
|
|
|
|
|
while (tempPath.back() != '/' && tempPath.back() != '\\')
|
|
|
|
tempPath.pop_back();
|
|
|
|
|
2016-11-09 16:48:28 +00:00
|
|
|
TextureTGA tempTex(std::string(tempPath + it->texture).c_str());
|
2016-11-08 15:42:05 +00:00
|
|
|
|
|
|
|
tempData->alpha = tempTex.hasAlpha();
|
|
|
|
tempData->width = tempTex.getWidth();
|
|
|
|
tempData->height = tempTex.getHeight();
|
2016-11-08 16:06:50 +00:00
|
|
|
tempData->data = new std::vector<std::uint8_t>(tempTex.getData());
|
2016-11-08 15:42:05 +00:00
|
|
|
}
|
|
|
|
catch (std::invalid_argument e)
|
|
|
|
{
|
|
|
|
GLubyte solidColor[4] = { 0, 0, 255, 255 };
|
|
|
|
tempData->alpha = true;
|
|
|
|
tempData->width = 1;
|
|
|
|
tempData->height = 1;
|
2016-11-08 16:06:50 +00:00
|
|
|
tempData->data = new std::vector<std::uint8_t>({ 0, 0, 255, 255 });
|
2016-11-08 15:42:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vTextures.push_back(tempData);
|
|
|
|
}
|
2016-09-06 13:15:29 +00:00
|
|
|
}
|