OpenGlController.cpp 9.75 KB
Newer Older
1 2 3 4 5 6
#include <gl\glew.h>
#include <gl\glfw3.h>
#include <Windows.h>
#include "OpenGLController.h"
#include "callback.h"

Anakin's avatar
Anakin committed
7 8 9
#include <glm\gtc\matrix_transform.hpp>
#include "shader.hpp"
#include "Texture.h"
Anakin's avatar
Anakin committed
10 11
#include <iostream>

Anakin's avatar
Anakin committed
12 13
#define VERTEX_SHADER "Shader/TextureShader.vert"
#define FRAGMENT_SHADER "Shader/TextureShader.frag"
14
#define MAX_MODEL_COUNT 1000
15 16 17 18

/////////////////////////////////////////////////////////////////////////
// public constructor/destructor

Anakin's avatar
Anakin committed
19
OpenGLController* OpenGLController::getInstance(int oglMajor, int oglMinor)
20
{
Anakin's avatar
Anakin committed
21
	static OpenGLController *instace = new OpenGLController(oglMajor, oglMinor);
Anakin's avatar
Anakin committed
22 23 24 25 26
	return instace;
}

OpenGLController::~OpenGLController()
{
27
	glDeleteBuffers(1, &gluiInstanceBufferID);
Anakin's avatar
Anakin committed
28 29 30 31
	glDeleteBuffers(1, &gluiVertexBufferID);
	glDeleteVertexArrays(1, &gluiVertexArrayID);
	glDeleteProgram(gluiShaderPrgmID);

Anakin's avatar
Anakin committed
32 33
	glDeleteTextures(1, &gluiSamplerID);
	glfwTerminate();
Anakin's avatar
Anakin committed
34 35 36 37 38 39 40 41 42 43 44

	while (!vModels.empty())
	{
		Modl* cursor = vModels.back();
		vModels.pop_back();
		
		delete cursor->uv;
		delete cursor->mesh;
		delete cursor->vertex;
		delete cursor;
	}
45 46
}

Anakin's avatar
Anakin committed
47 48 49 50

/////////////////////////////////////////////////////////////////////////
// private constructor

Anakin's avatar
Anakin committed
51
OpenGLController::OpenGLController(int oglMajor, int oglMinor)
52
{
53
	// adjust ogl version optional
54 55
	iOglMajorVersion = oglMajor;
	iOglMinorVersion = oglMinor;
Anakin's avatar
Anakin committed
56 57

	// run OGL
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
	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);
Anakin's avatar
Anakin committed
80 81 82 83 84 85

	// generate stuff
	glGenVertexArrays(1, &gluiVertexArrayID);
	glBindVertexArray(gluiVertexArrayID);

	glGenBuffers(1, &gluiVertexBufferID);
86 87 88 89 90 91 92 93
	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);

Anakin's avatar
Anakin committed
94
	glBindBuffer(GL_ARRAY_BUFFER, gluiInstanceBufferID);
Anakin's avatar
Anakin committed
95 96 97 98
	glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 0));
	glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 4));
	glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 8));
	glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 12));
Anakin's avatar
Anakin committed
99 100
	glBindBuffer(GL_ARRAY_BUFFER, 0);

Anakin's avatar
Anakin committed
101
	// enable position, UV and mvp
102 103
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
Anakin's avatar
Anakin committed
104

Anakin's avatar
Anakin committed
105 106 107 108 109 110 111 112 113 114 115
	glEnableVertexAttribArray(2);
	glEnableVertexAttribArray(3);
	glEnableVertexAttribArray(4);
	glEnableVertexAttribArray(5);

	// MPV only once per instance
	glVertexAttribDivisor(2, 1);
	glVertexAttribDivisor(3, 1);
	glVertexAttribDivisor(4, 1);
	glVertexAttribDivisor(5, 1);

116 117 118
	// set buffer size
	glBufferData(GL_ARRAY_BUFFER, MAX_MODEL_COUNT * sizeof(glm::mat4), NULL, GL_STREAM_DRAW);

Anakin's avatar
Anakin committed
119 120 121 122 123 124 125 126 127 128 129 130 131
	// 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");
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
}

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 ";
155
		message += std::to_string(iOglMajorVersion);
156
		message += ".";
157 158
		message += std::to_string(iOglMinorVersion);
		message += "\nTry to use an other version";
159 160 161 162 163 164 165 166 167 168 169

		MessageBox(NULL, message.c_str(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);

		glfwTerminate();
		exit(0);
	}

	glfwSetWindowUserPointer(pWindow, this);
	glfwMakeContextCurrent(pWindow);
}

Anakin's avatar
Anakin committed
170 171 172 173 174 175 176 177 178 179 180 181
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);
	}
}

182 183 184 185 186 187 188 189 190 191 192
void OpenGLController::setCallbackFunctions()
{
	glfwSetMouseButtonCallback(pWindow, mouseButton);
	glfwSetCursorPosCallback(pWindow, mouseMove);
	glfwSetWindowSizeCallback(pWindow, windowResize);
	glfwSetScrollCallback(pWindow, mouseWheel);
	glfwSetKeyCallback(pWindow, keyPress);
}

glm::mat4 OpenGLController::getMVPMatrix()
{
Anakin's avatar
Anakin committed
193 194 195 196 197
	// Projection
	glm::mat4 m4x4Projection = glm::perspective(fFOV, float(iWidth) / float(iHeight), fMinView, fMaxView);
	
	// View
	glm::mat4 m4x4View = glm::lookAt(
Anakin's avatar
Anakin committed
198 199 200 201
		glm::vec3(dTranslationX, dTranslationY, dTranslationZ),
		glm::vec3(dTranslationX, dTranslationY, dTranslationZ - 1),
		glm::vec3(0, 1, 0)
	);
Anakin's avatar
Anakin committed
202

Anakin's avatar
Anakin committed
203
	// Model
Anakin's avatar
Anakin committed
204
	//TODO for all
Anakin's avatar
Anakin committed
205 206 207 208 209 210 211 212 213 214
	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;
215 216
}

Anakin's avatar
Anakin committed
217 218 219 220

/////////////////////////////////////////////////////////////////////////
// public getter

221 222 223 224 225 226 227 228 229 230 231
GLFWwindow * OpenGLController::getWindow() const
{
	return pWindow;
}


/////////////////////////////////////////////////////////////////////////
// public functions

void OpenGLController::resize(int width, int height)
{
Anakin's avatar
Anakin committed
232 233
	iWidth = width;
	iHeight = height;
234 235 236 237
}

void OpenGLController::addRotX(float value)
{
Anakin's avatar
Anakin committed
238
	fRotationX += value;
239 240 241 242
}

void OpenGLController::addRotY(float value)
{
Anakin's avatar
Anakin committed
243
	fRotationY += value;
244 245 246 247
}

void OpenGLController::addTransX(double value)
{
Anakin's avatar
Anakin committed
248
	dTranslationX += value;
249 250 251 252
}

void OpenGLController::addTransY(double value)
{
Anakin's avatar
Anakin committed
253
	dTranslationY += value;
254 255 256 257
}

void OpenGLController::addTransZ(double value)
{
Anakin's avatar
Anakin committed
258
	dTranslationZ += value;
259 260 261 262 263 264 265 266
}

void OpenGLController::updateScene()
{
	// get new matrices
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// use shader prgm
Anakin's avatar
Anakin committed
267
	glUseProgram(gluiShaderPrgmID);
268

Anakin's avatar
Anakin committed
269 270 271 272 273
	// fill vector with MVPs of all Models (only 1 for testing)
	std::vector<glm::mat4> mvpMatrices;
	mvpMatrices.push_back(getMVPMatrix());

	// give the MVPs to the shader
Anakin's avatar
Anakin committed
274
	glBindBuffer(GL_UNIFORM_BUFFER, gluiInstanceBufferID);
Anakin's avatar
Anakin committed
275
	glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * mvpMatrices.size(), NULL, mvpMatrices.data());
Anakin's avatar
Anakin committed
276
	glBindBuffer(GL_UNIFORM_BUFFER, 0);
277 278 279

	// bind texture in texture unit 0
	glActiveTexture(GL_TEXTURE0);
Anakin's avatar
Anakin committed
280
	glBindTexture(GL_TEXTURE_2D, gluiTextureID);
281 282 283
	// tell sampler to use texture unit 0
	glUniform1i(gluiSamplerID, 0);

Anakin's avatar
Anakin committed
284 285
	//draw objects hardcoded only 1 instance for testing
	glDrawArraysInstanced(GL_TRIANGLES, 0, vModels.front()->meshSize, 1);
286

Anakin's avatar
Anakin committed
287 288 289 290 291 292 293
	glfwSwapBuffers(pWindow);
	glfwPollEvents();

}

void OpenGLController::loadMsh(const char * path)
{
294
	// get data
295 296 297
	try
	{
		Object obj(path);
Anakin's avatar
Anakin committed
298
		vModels = obj.getModels();
299 300 301 302 303 304 305
	}
	catch (std::invalid_argument e)
	{
		MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
		exit(1);
	}

306 307
	glGenTextures(1, &gluiTextureID);
	glBindTexture(GL_TEXTURE_2D, gluiTextureID);
Anakin's avatar
Anakin committed
308

309 310
	try
	{
Anakin's avatar
Anakin committed
311 312 313
		////TODO: for all
		if (vModels.front()->texture == "")
			throw std::invalid_argument("no texture name");
314

315 316 317 318 319
		std::string tempPath = path;

		while (tempPath.back() != '/' && tempPath.back() != '\\')
			tempPath.pop_back();

Anakin's avatar
Anakin committed
320 321 322 323 324 325 326 327 328 329
		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()
					);
330 331 332
	}
	catch (std::invalid_argument e)
	{
Anakin's avatar
Anakin committed
333
		GLubyte solidColor[4] = { 255, 0, 0, 255};
Anakin's avatar
Anakin committed
334 335 336 337 338 339 340 341 342 343
		glTexImage2D(GL_TEXTURE_2D,
					 0,
					 GL_RGBA,
					 1,
					 1,
					 0,
					 GL_RGBA,
					 GL_UNSIGNED_BYTE,
					 (const GLvoid*)solidColor
					);
344
	}
Anakin's avatar
Anakin committed
345

346 347 348 349 350
	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);
Anakin's avatar
Anakin committed
351

Anakin's avatar
Anakin committed
352
	////TODO: for all
353
	std::vector<Vertex> tempBufferData;
Anakin's avatar
Anakin committed
354 355 356

	for (unsigned int i = 0; i < vModels.front()->meshSize; i++)
	{
357 358 359 360
		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];
Anakin's avatar
Anakin committed
361

362 363 364 365 366 367
		if (vModels.front()->uv == NULL)
		{
			tempVertex.uv[0] = 1.0;
			tempVertex.uv[1] = 1.0;
		}
		else
Anakin's avatar
Anakin committed
368
		{
369 370
			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];
Anakin's avatar
Anakin committed
371
		}
372 373

		tempBufferData.push_back(tempVertex);
Anakin's avatar
Anakin committed
374 375
	}

376
	glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID);
Anakin's avatar
Anakin committed
377 378
	glBufferData(
		GL_ARRAY_BUFFER,
379
		sizeof(Vertex) * tempBufferData.size(),
380
		tempBufferData.data(),
Anakin's avatar
Anakin committed
381 382
		GL_STATIC_DRAW
	);
383
}