SWBF2-Classic-Msh-Viewer/MshViewer/Source/OpenGlController.cpp

399 lines
9.2 KiB
C++

#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 "import.h"
#include "Texture.h"
#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();
}
/////////////////////////////////////////////////////////////////////////
// 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);
}
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)
{
// generate stuff
glGenVertexArrays(1, &gluiVertexArrayID);
glBindVertexArray(gluiVertexArrayID);
glGenBuffers(1, &gluiVertexBufferID);
glGenBuffers(1, &gluiUVBufferID);
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");
// get data
std::list<std::string> listTextures;
try
{
Object obj(path);
vModels = obj.getModels();
//vfVertices = obj.getVertex();
//vfUV = obj.getUV();
//listTextures = obj.getTexture();
//ui32MeshSize = obj.getSize();
}
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<GLfloat> 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<GLfloat> 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
);
}