OpenGlController.cpp 12.4 KB
Newer Older
1 2
#include "OpenGLController.h"
#include "callback.h"
Anakin's avatar
Anakin committed
3 4
#include "shader.hpp"
#include "Texture.h"
Anakin's avatar
Anakin committed
5 6 7 8
#include <Windows.h>
#include <string>
#include <glm\gtc\matrix_transform.hpp>

Anakin's avatar
Anakin committed
9

Anakin's avatar
Anakin committed
10 11
#define VERTEX_SHADER "Shader/TextureShader.vert"
#define FRAGMENT_SHADER "Shader/TextureShader.frag"
12 13 14 15

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

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

OpenGLController::~OpenGLController()
{
Anakin's avatar
Anakin committed
24 25 26 27
	glDeleteBuffers(1, &gluiVertexBufferID);
	glDeleteVertexArrays(1, &gluiVertexArrayID);
	glDeleteProgram(gluiShaderPrgmID);

Anakin's avatar
Anakin committed
28 29
	glDeleteTextures(1, &gluiSamplerID);
	glfwTerminate();
Anakin's avatar
Anakin committed
30

31
	deleteVectors();
32 33
}

Anakin's avatar
Anakin committed
34 35 36 37

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

Anakin's avatar
Anakin committed
38
OpenGLController::OpenGLController(int oglMajor, int oglMinor)
39
{
40
	// adjust ogl version optional
41 42
	iOglMajorVersion = oglMajor;
	iOglMinorVersion = oglMinor;
Anakin's avatar
Anakin committed
43 44

	// run OGL
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
	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
67 68 69 70 71 72

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

	glGenBuffers(1, &gluiVertexBufferID);
73 74 75 76 77 78 79

	// 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
80
	// enable position, UV and mvp
81 82
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
Anakin's avatar
Anakin committed
83 84 85 86 87 88 89 90 91 92 93 94

	// 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);
	}

95
	// get some shader IDs
Anakin's avatar
Anakin committed
96 97
	gluiMatrixID = glGetUniformLocation(gluiShaderPrgmID, "MVP");
	gluiSamplerID = glGetUniformLocation(gluiShaderPrgmID, "textureSampler");
98 99 100 101

	// generate texture
	glGenTextures(1, &gluiTextureID);
	glBindTexture(GL_TEXTURE_2D, gluiTextureID);
Anakin's avatar
Anakin committed
102 103 104 105 106 107

	// 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);
108 109
}

110 111
void OpenGLController::deleteVectors()
{
112
	if (vModels != NULL)
113
	{
114
		while (!vModels->empty())
Anakin's avatar
Anakin committed
115
		{
Anakin's avatar
Anakin committed
116
			Modl* modelVectorElement = vModels->back();
117
			vModels->pop_back();
118

Anakin's avatar
Anakin committed
119
			while (!modelVectorElement->segmLst.empty())
120
			{
Anakin's avatar
Anakin committed
121 122
				Segment* segmentVectorElement = modelVectorElement->segmLst.back();
				modelVectorElement->segmLst.pop_back();
123

Anakin's avatar
Anakin committed
124 125
				delete[] segmentVectorElement->uv;
				delete[] segmentVectorElement->vertex;
126

Anakin's avatar
Anakin committed
127
				while (!segmentVectorElement->meshIndices.empty())
128
				{
Anakin's avatar
Anakin committed
129 130
					segmentVectorElement->meshIndices.back().clear();
					segmentVectorElement->meshIndices.pop_back();
131 132
				}

Anakin's avatar
Anakin committed
133
				delete segmentVectorElement;
134 135
			}

Anakin's avatar
Anakin committed
136
			delete modelVectorElement;
Anakin's avatar
Anakin committed
137
		}
138
		delete vModels;
139 140 141 142 143 144
	}

	while (!vTextures.empty())
	{
		textureData* cursor = vTextures.back();
		vTextures.pop_back();
145
		cursor->data->clear();
146 147 148 149 150
		delete cursor->data;
		delete cursor;
	}
}

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
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 ";
172
		message += std::to_string(iOglMajorVersion);
173
		message += ".";
174 175
		message += std::to_string(iOglMinorVersion);
		message += "\nTry to use an other version";
176 177 178 179 180 181 182 183 184 185 186

		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
187 188 189 190 191 192 193 194 195 196 197 198
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);
	}
}

199 200 201 202 203 204 205
void OpenGLController::setCallbackFunctions()
{
	glfwSetMouseButtonCallback(pWindow, mouseButton);
	glfwSetCursorPosCallback(pWindow, mouseMove);
	glfwSetWindowSizeCallback(pWindow, windowResize);
	glfwSetScrollCallback(pWindow, mouseWheel);
	glfwSetKeyCallback(pWindow, keyPress);
Anakin's avatar
Anakin committed
206
	glfwSetDropCallback(pWindow, dragNdrop);
207 208
}

Anakin's avatar
Anakin committed
209 210 211 212
glm::mat4 OpenGLController::getModelMatrix(unsigned int index)
{
	glm::mat4 tempParentMatrix = glm::mat4(1.0f);

213
	for (unsigned int loop = 0; loop < vModels->size(); loop++)
Anakin's avatar
Anakin committed
214
	{
215
		if (!strcmp(vModels->at(index)->parent.c_str(), vModels->at(loop)->name.c_str()))
Anakin's avatar
Anakin committed
216 217 218 219 220 221
		{
			tempParentMatrix = getModelMatrix(loop);
			break;
		}
	}

222
	return tempParentMatrix * vModels->at(index)->m4x4Translation;
Anakin's avatar
Anakin committed
223 224
}

Anakin's avatar
Anakin committed
225
glm::mat4 OpenGLController::getMVPMatrix(unsigned int index)
226
{
227 228 229 230 231
	// Projection
	glm::mat4 m4x4Projection = glm::perspective(fFOV, float(iWidth) / float(iHeight), fMinView, fMaxView);
	
	// View
	glm::mat4 m4x4View = glm::lookAt(
Anakin's avatar
Anakin committed
232 233 234 235
		glm::vec3(dTranslationX, dTranslationY, dTranslationZ),
		glm::vec3(dTranslationX, dTranslationY, dTranslationZ - 1),
		glm::vec3(0, 1, 0)
	);
Anakin's avatar
Anakin committed
236

237 238 239 240 241 242
	// 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));

Anakin's avatar
Anakin committed
243
	// move to center
Anakin's avatar
Anakin committed
244 245 246 247 248
	glm::mat4 m4x4ModelCenter = glm::translate(
		glm::mat4(1.0f),
		glm::vec3(-sceneBoundingBox.center[0], -sceneBoundingBox.center[1], -sceneBoundingBox.center[2])
	);

Anakin's avatar
Anakin committed
249 250 251 252 253
	//scale to 1
	float maxExtent = max(max(sceneBoundingBox.extents[0], sceneBoundingBox.extents[1]), sceneBoundingBox.extents[2]);
	glm::mat4 m4x4Normalize = glm::mat4(1.0f); 
	m4x4Normalize = glm::scale(m4x4Normalize, glm::vec3(1/maxExtent, 1 / maxExtent, 1 / maxExtent));

254
	// Return MVP
Anakin's avatar
Anakin committed
255
	return m4x4Projection * m4x4View * m4x4ModelRot * m4x4Normalize * m4x4ModelCenter * getModelMatrix(index);
256 257
}

Anakin's avatar
Anakin committed
258 259 260 261

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

262 263 264 265 266 267 268 269 270 271 272
GLFWwindow * OpenGLController::getWindow() const
{
	return pWindow;
}


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

void OpenGLController::resize(int width, int height)
{
Anakin's avatar
Anakin committed
273 274
	iWidth = width;
	iHeight = height;
275 276 277 278
}

void OpenGLController::addRotX(float value)
{
Anakin's avatar
Anakin committed
279
	fRotationX += value;
280 281 282 283
}

void OpenGLController::addRotY(float value)
{
Anakin's avatar
Anakin committed
284
	fRotationY += value;
285 286 287 288
}

void OpenGLController::addTransX(double value)
{
Anakin's avatar
Anakin committed
289
	dTranslationX += value;
290 291 292 293
}

void OpenGLController::addTransY(double value)
{
Anakin's avatar
Anakin committed
294
	dTranslationY += value;
295 296 297 298
}

void OpenGLController::addTransZ(double value)
{
Anakin's avatar
Anakin committed
299
	dTranslationZ += value;
300 301
}

302 303 304 305 306 307 308 309 310 311
void OpenGLController::resetView()
{
	dTranslationX = 0;
	dTranslationY = 0;
	dTranslationZ = 5;
	fRotationX = 0;
	fRotationY = 0;
	fRotationZ = 0;
}

312 313 314 315 316 317
void OpenGLController::updateScene()
{
	// get new matrices
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// use shader prgm
Anakin's avatar
Anakin committed
318
	glUseProgram(gluiShaderPrgmID);
319 320 321

	// bind texture in texture unit 0
	glActiveTexture(GL_TEXTURE0);
Anakin's avatar
Anakin committed
322
	glBindTexture(GL_TEXTURE_2D, gluiTextureID);
323 324 325
	// tell sampler to use texture unit 0
	glUniform1i(gluiSamplerID, 0);

Anakin's avatar
Anakin committed
326
	if (vModels != NULL)
Anakin's avatar
Anakin committed
327
	{
Anakin's avatar
Anakin committed
328 329 330
		int instanceOffset(0);

		for (unsigned int modelIndex = 0; modelIndex < vModels->size(); modelIndex++)
Anakin's avatar
Anakin committed
331
		{
Anakin's avatar
Anakin committed
332 333 334 335 336 337 338 339 340 341 342
			// skip null, bones, shadowMesh, hidden things (don't increase textrue index!!)
			if (vModels->at(modelIndex)->type == null ||
				vModels->at(modelIndex)->type == bone ||
				vModels->at(modelIndex)->type == shadowMesh ||
				vModels->at(modelIndex)->renderFlags == 1)
				continue;

			for (auto& segIt : vModels->at(modelIndex)->segmLst)
			{
				// give texture to the shader
				std::uint32_t tempTexIndex = segIt->textureIndex >= vTextures.size() ? vTextures.size() - 1 : segIt->textureIndex;
343

Anakin's avatar
Anakin committed
344 345 346 347 348 349 350 351 352 353 354
				glTexImage2D(
					GL_TEXTURE_2D,
					0,
					vTextures[tempTexIndex]->alpha ? GL_RGBA : GL_RGB,
					vTextures[tempTexIndex]->width,
					vTextures[tempTexIndex]->height,
					0,
					vTextures[tempTexIndex]->alpha ? GL_BGRA : GL_BGR,
					GL_UNSIGNED_BYTE,
					vTextures[tempTexIndex]->data->data()
				);
Anakin's avatar
Anakin committed
355

Anakin's avatar
Anakin committed
356
				glGenerateMipmap(GL_TEXTURE_2D);
Anakin's avatar
Anakin committed
357

Anakin's avatar
Anakin committed
358 359
				// give the MVP to the shader
				glUniformMatrix4fv(gluiMatrixID, 1, GL_FALSE, &getMVPMatrix(modelIndex)[0][0]);
Anakin's avatar
Anakin committed
360

Anakin's avatar
Anakin committed
361 362 363 364
				// calculate the number of vertex
				unsigned int vertexCount(0);
				for (auto& it : segIt->meshIndices)
					vertexCount += (it.size() - 2) * 3;
Anakin's avatar
Anakin committed
365 366


Anakin's avatar
Anakin committed
367
				glDrawArrays(GL_TRIANGLES, instanceOffset, vertexCount);
Anakin's avatar
Anakin committed
368

Anakin's avatar
Anakin committed
369 370 371
				// increase the offset
				instanceOffset += vertexCount;
			}
Anakin's avatar
Anakin committed
372
		}
Anakin's avatar
Anakin committed
373
	}
Anakin's avatar
Anakin committed
374 375 376 377 378 379
	glfwSwapBuffers(pWindow);
	glfwPollEvents();
}

void OpenGLController::loadMsh(const char * path)
{
380 381 382
	// clean up old stuff first
	deleteVectors();

Anakin's avatar
Anakin committed
383 384
	std::vector<std::string> tempTexList;

385
	// get all models
386 387 388
	try
	{
		Object obj(path);
Anakin's avatar
Anakin committed
389
		vModels = obj.getModels();
Anakin's avatar
Anakin committed
390
		tempTexList = obj.getTextureList();
Anakin's avatar
Anakin committed
391
		sceneBoundingBox = obj.getBoundgBox();
392 393 394 395
	}
	catch (std::invalid_argument e)
	{
		MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
Anakin's avatar
Anakin committed
396
		return;
397 398
	}

399
	// collect vertex data of all models
400
	std::vector<Vertex> tempBufferData;
401

402
	for (auto& modIt : *vModels)		// for every model chunk
403
	{
Anakin's avatar
Anakin committed
404
		for (auto& segIt : modIt->segmLst)		// for every cluster
405
		{
Anakin's avatar
Anakin committed
406
			for (auto& mshIt : segIt->meshIndices)		// for every polygon
407
			{
Anakin's avatar
Anakin committed
408
				if (mshIt.size() >= 3)		// multipoly
409
				{
Anakin's avatar
Anakin committed
410
					// for every triangle of the multi polygon
Anakin's avatar
Anakin committed
411
					for (unsigned int tri = 0; tri < mshIt.size() - 2; tri++)
Anakin's avatar
Anakin committed
412 413 414 415 416 417 418
					{
						// for every edge of the triangle
						for (int triEdge = 0; triEdge < 3; triEdge++)
						{
							Vertex tempVertex;
							// every edge has 3 coordinates
							for (int j = 0; j < 3; j++)
Anakin's avatar
Anakin committed
419
								tempVertex.position[j] = (GLfloat)segIt->vertex[mshIt[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 3 + j];
Anakin's avatar
Anakin committed
420

Anakin's avatar
Anakin committed
421 422 423 424 425 426 427 428 429
							// and 2 UV
							if (segIt->uv == NULL)
							{
								tempVertex.uv[0] = 1.0;
								tempVertex.uv[1] = 1.0;
							}
							else
							{
								for (int j = 0; j < 2; j++)
Anakin's avatar
Anakin committed
430
									tempVertex.uv[j] = (GLfloat)segIt->uv[mshIt[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 2 + j];
Anakin's avatar
Anakin committed
431 432 433 434
							}
							tempBufferData.push_back(tempVertex);
						}
					}
435
				}
Anakin's avatar
Anakin committed
436
				else	// this shouldn't happen (polygon with less then 3 vertex)
437 438 439 440 441 442 443
				{
					deleteVectors();
					MessageBox(NULL, "You have polygons with less then 3 vertices!", "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
					return;
				}
			}
		}
Anakin's avatar
Anakin committed
444 445
	}

446
	// fill the buffer
447
	glBindBuffer(GL_ARRAY_BUFFER, gluiVertexBufferID);
Anakin's avatar
Anakin committed
448 449
	glBufferData(
		GL_ARRAY_BUFFER,
450
		sizeof(Vertex) * tempBufferData.size(),
451
		tempBufferData.data(),
Anakin's avatar
Anakin committed
452 453
		GL_STATIC_DRAW
	);
Anakin's avatar
Anakin committed
454
	glBindBuffer(GL_ARRAY_BUFFER, 0);
Anakin's avatar
Anakin committed
455

Anakin's avatar
Anakin committed
456 457
	tempBufferData.clear();

458

Anakin's avatar
Anakin committed
459 460
	// get textures path
	std::string tempPath = path;
461

Anakin's avatar
Anakin committed
462 463
	while (tempPath.back() != '/' && tempPath.back() != '\\')
		tempPath.pop_back();
464

Anakin's avatar
Anakin committed
465 466 467 468
	// load all textures;
	for (auto& texIt : tempTexList)
	{
		textureData* tempData = new textureData;
469

Anakin's avatar
Anakin committed
470 471 472
		try
		{
			TextureTGA tempTex(std::string(tempPath + texIt).c_str());
473

Anakin's avatar
Anakin committed
474 475 476
			tempData->alpha = tempTex.hasAlpha();
			tempData->width = tempTex.getWidth();
			tempData->height = tempTex.getHeight();
477
			tempData->data = tempTex.getData();
Anakin's avatar
Anakin committed
478
		}
Anakin's avatar
Anakin committed
479 480 481 482 483 484 485 486 487
		catch (std::invalid_argument e)
		{
			tempData->alpha = true;
			tempData->width = 1;
			tempData->height = 1;
			tempData->data = new std::vector<std::uint8_t>({ 0, 0, 255, 255 });
		}

		vTextures.push_back(tempData);
488
	}
Anakin's avatar
Anakin committed
489 490 491 492 493 494 495 496 497 498

	// add a solid default color at the end (maybe there is an invalid index later)
	textureData* tempData = new textureData;
	tempData->alpha = true;
	tempData->width = 1;
	tempData->height = 1;
	tempData->data = new std::vector<std::uint8_t>({ 0, 0, 255, 255 });
	vTextures.push_back(tempData);

	tempTexList.clear();
499
}