GeometryEngine.cpp 4.45 KB
Newer Older
1
#include "..\Header\GeometryEngine.h"
Anakin's avatar
Anakin committed
2
#include "..\Header\MshFile.h"
3

Anakin's avatar
Anakin committed
4 5 6 7

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

8
GeometryEngine::GeometryEngine()
Anakin's avatar
Anakin committed
9
	: m_indexBuf(QOpenGLBuffer::IndexBuffer)
10
{
Anakin's avatar
Anakin committed
11
	initializeOpenGLFunctions();
12

Anakin's avatar
Anakin committed
13
	// Generate 2 VBOs
Anakin's avatar
Anakin committed
14 15
	m_arrayBuf.create();
	m_indexBuf.create();
16

Anakin's avatar
Anakin committed
17
	// Initializes cube geometry and transfers it to VBOs
Anakin's avatar
Anakin committed
18
	loadFile("..\\Release\\Msh\\triClothMan.msh");
19 20 21 22
}

GeometryEngine::~GeometryEngine()
{
Anakin's avatar
Anakin committed
23 24 25 26 27 28
	m_arrayBuf.destroy();
	m_indexBuf.destroy();

	for (auto it : m_textures)
		delete it;
	m_textures.clear();
Anakin's avatar
Anakin committed
29
	m_drawList.clear();
30 31
}

Anakin's avatar
Anakin committed
32 33 34 35

/////////////////////////////////////////////////////////////////////////
// private functions

Anakin's avatar
Anakin committed
36
void GeometryEngine::loadFile(const char* filePath)
37
{
Anakin's avatar
Anakin committed
38 39
	try
	{
Anakin's avatar
Anakin committed
40
		//TODO normalize
Anakin's avatar
Anakin committed
41 42 43 44 45 46 47 48 49 50

		QVector<Model*>* models;
		QVector<std::string>* textureNames;
		QVector<VertexData> vertexData;
		QVector<GLuint> indexData;

		// open file and get the information
		MshFile file(filePath);
		models = file.getModels();
		textureNames = file.getTextureNames();
Anakin's avatar
Anakin committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

		// collect data
		unsigned int offsetCount(0);
		for (auto& modelIterator : *models)
		{
			for (auto& segmentIterator : modelIterator->segmList)
			{
				// get draw information
				DrawInformation new_info;
				new_info.offset = offsetCount;
				new_info.size = segmentIterator->indices.size();
				new_info.textureIndex = segmentIterator->textureIndex;
				new_info.modelMatrix = modelIterator->m4x4Translation;

				// add offset to indices
				for (auto& it : segmentIterator->indices)
					it += new_info.offset;

				// save data
				vertexData += segmentIterator->vertices;
				indexData += segmentIterator->indices;
				m_drawList.push_back(new_info);

				// update offset
				offsetCount += new_info.size;
			}
		}

Anakin's avatar
Anakin committed
79 80
		//TODO: cleanup old stuff

Anakin's avatar
Anakin committed
81 82 83 84 85 86 87 88
		// Transfer vertex data to VBO 0
		m_arrayBuf.bind();
		m_arrayBuf.allocate(vertexData.data(), vertexData.size() * sizeof(VertexData));

		// Transfer index data to VBO 1
		m_indexBuf.bind();
		m_indexBuf.allocate(indexData.data(), indexData.size() * sizeof(GLuint));

Anakin's avatar
Anakin committed
89 90 91 92 93 94 95 96 97
		// get textures path
		std::string path = filePath;

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

		// load the textures
		for(auto& it : *textureNames)
			loadTexture(std::string(path + it).c_str());
Anakin's avatar
Anakin committed
98

Anakin's avatar
Anakin committed
99 100 101 102 103 104
	}
	catch (std::invalid_argument e)
	{
		//TODO: make a cool message box
		auto msg = e.what();
	}
105

Anakin's avatar
Anakin committed
106
	
107 108
}

Anakin's avatar
Anakin committed
109
void GeometryEngine::loadTexture(const char* filePath)
110
{
Anakin's avatar
Anakin committed
111 112 113 114 115 116 117 118 119 120
	
	QImage img;
	if (!img.load(filePath))
	{
		img = QImage(1, 1, QImage::Format_RGB32);
		img.fill(Qt::red);
	}

	// Load image to OglTexture
	QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored());
Anakin's avatar
Anakin committed
121 122

	// Set nearest filtering mode for texture minification
Anakin's avatar
Anakin committed
123
	new_texture->setMinificationFilter(QOpenGLTexture::Nearest);
Anakin's avatar
Anakin committed
124 125

	// Set bilinear filtering mode for texture magnification
Anakin's avatar
Anakin committed
126
	new_texture->setMagnificationFilter(QOpenGLTexture::Linear);
Anakin's avatar
Anakin committed
127 128 129

	// Wrap texture coordinates by repeating
	// f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
Anakin's avatar
Anakin committed
130 131 132
	new_texture->setWrapMode(QOpenGLTexture::Repeat);

	m_textures.push_back(new_texture);
Anakin's avatar
Anakin committed
133 134
}

Anakin's avatar
Anakin committed
135 136 137 138

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

Anakin's avatar
Anakin committed
139 140
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
{
Anakin's avatar
Anakin committed
141
// Setup
Anakin's avatar
Anakin committed
142
	// Tell OpenGL which VBOs to use
Anakin's avatar
Anakin committed
143 144
	m_arrayBuf.bind();
	m_indexBuf.bind();
Anakin's avatar
Anakin committed
145

Anakin's avatar
Anakin committed
146
	// Allways use texture unit 0
Anakin's avatar
Anakin committed
147
	program->setUniformValue("texture", 0);
148

Anakin's avatar
Anakin committed
149 150
	// Offset for position
	quintptr offset = 0;
151

Anakin's avatar
Anakin committed
152 153 154 155
	// Tell OpenGL programmable pipeline how to locate vertex position data
	int vertexLocation = program->attributeLocation("a_position");
	program->enableAttributeArray(vertexLocation);
	program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
156

Anakin's avatar
Anakin committed
157 158
	// Offset for texture coordinate
	offset += sizeof(QVector3D);
159

Anakin's avatar
Anakin committed
160 161 162 163
	// Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
	int texcoordLocation = program->attributeLocation("a_texcoord");
	program->enableAttributeArray(texcoordLocation);
	program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));
164

Anakin's avatar
Anakin committed
165 166 167 168 169 170 171
// Paint

	for (auto& it : m_drawList)
	{
		// bind the correct texture
		if (it.textureIndex < m_textures.size())
			m_textures.at(it.textureIndex)->bind();
Anakin's avatar
Anakin committed
172 173
		else
			m_textures.last()->bind();
Anakin's avatar
Anakin committed
174 175 176 177 178 179 180

		// Set model matrix
		program->setUniformValue("m_matrix", it.modelMatrix);

		// Draw cube geometry using indices from VBO 1
		glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint)));
	}
181
}