GeometryEngine.cpp 6.28 KB
Newer Older
1
#include "..\Header\GeometryEngine.h"
Anakin's avatar
Anakin committed
2
#include "..\Header\MshFile.h"
3
4
#include "..\Header\OglViewerWidget.h"
#include "..\Header\MainWindow.h"
5
#include "..\Header\OutputDevice.h"
Anakin's avatar
Anakin committed
6
#include <QRegExp>
7

Anakin's avatar
Anakin committed
8
9

/////////////////////////////////////////////////////////////////////////
10
// constructor/destructor
Anakin's avatar
Anakin committed
11

12
13
14
GeometryEngine::GeometryEngine(QObject *parent)
	: QObject(parent)
	, m_indexBuf(QOpenGLBuffer::IndexBuffer)
15
	, m_defaultMaterial(FileInterface::getDefaultMaterial())
16
{
Anakin's avatar
Anakin committed
17
	initializeOpenGLFunctions();
18
19
20
21
}

GeometryEngine::~GeometryEngine()
{
Anakin's avatar
Anakin committed
22
	clearData();
23
	delete m_defaultMaterial->texture0;
Anakin's avatar
Anakin committed
24
	delete m_defaultMaterial;
25
26
}

Anakin's avatar
Anakin committed
27
28

/////////////////////////////////////////////////////////////////////////
29
// functions
Anakin's avatar
Anakin committed
30

Anakin's avatar
Anakin committed
31
32
33
34
35
36
37
void GeometryEngine::clearData()
{
	if (m_arrayBuf.isCreated())
		m_arrayBuf.destroy();
	if (m_indexBuf.isCreated())
		m_indexBuf.destroy();

38
39
40
	if (m_materials != Q_NULLPTR)
	{
		for (auto it : *m_materials)
Anakin's avatar
Anakin committed
41
42
43
44
45
46
47
		{
			if (it.texture0 != Q_NULLPTR)
				delete it.texture0;

			if (it.texture1 != Q_NULLPTR)
				delete it.texture1;
		}
48
49
50
		m_materials->clear();
		delete m_materials;
	}
Anakin's avatar
Anakin committed
51
52
53
	m_drawList.clear();
}

Anakin's avatar
Anakin committed
54
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
Anakin's avatar
Anakin committed
55
{
Anakin's avatar
Anakin committed
56
57
58
	if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
		return;

59
	// Setup
Anakin's avatar
Anakin committed
60
	// Tell OpenGL which VBOs to use
Anakin's avatar
Anakin committed
61
62
	m_arrayBuf.bind();
	m_indexBuf.bind();
Anakin's avatar
Anakin committed
63

Anakin's avatar
Anakin committed
64
65
66
67
68
69
70
	// Allways normalize by this
	QMatrix4x4 normMatrix;
	float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
	normMatrix.scale(1 / maxExtent);
	normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
	program->setUniformValue("norm_matrix", normMatrix);

Anakin's avatar
Anakin committed
71
	// Allways use texture unit 0
Anakin's avatar
Anakin committed
72
	program->setUniformValue("texture", 0);
73

Anakin's avatar
Anakin committed
74
75
	// Offset for position
	quintptr offset = 0;
76

Anakin's avatar
Anakin committed
77
78
79
80
	// 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));
81

Anakin's avatar
Anakin committed
82
83
	// Offset for texture coordinate
	offset += sizeof(QVector3D);
84

Anakin's avatar
Anakin committed
85
86
87
88
	// 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));
89

Anakin's avatar
Anakin committed
90
91
92
93
94
95
96
97
	//Offset for normal
	offset += sizeof(QVector2D);

	// Tell OpenGL programmable pipeline how to locate vertex normal data
	int normLocation = program->attributeLocation("a_normal");
	program->enableAttributeArray(normLocation);
	program->setAttributeBuffer(normLocation, GL_FLOAT, offset, 3, sizeof(VertexData));

98
	// Paint
Anakin's avatar
Anakin committed
99
100
101

	for (auto& it : m_drawList)
	{
Anakin's avatar
Anakin committed
102
		bool tmp_transparent(false);
Anakin's avatar
Anakin committed
103
		bool tmp_specular(false);
Anakin's avatar
Anakin committed
104
		float shininess(0.0);
Anakin's avatar
Anakin committed
105
		QVector3D specularColor;
Anakin's avatar
Anakin committed
106

Anakin's avatar
Anakin committed
107
		// bind the correct texture
108
		if (it.textureIndex < (unsigned)m_materials->size() && m_materials->at(it.textureIndex).texture0 != Q_NULLPTR)
Anakin's avatar
Anakin committed
109
		{
110
			m_materials->at(it.textureIndex).texture0->bind();
Anakin's avatar
Anakin committed
111
			tmp_transparent = m_materials->at(it.textureIndex).transparent;
Anakin's avatar
Anakin committed
112
			tmp_specular = m_materials->at(it.textureIndex).flags[7];
Anakin's avatar
Anakin committed
113
			shininess = m_materials->at(it.textureIndex).shininess;
Anakin's avatar
Anakin committed
114
			specularColor = m_materials->at(it.textureIndex).specularColor.toVector3D();
Anakin's avatar
Anakin committed
115
		}
Anakin's avatar
Anakin committed
116
		else
Anakin's avatar
Anakin committed
117
		{
118
			m_defaultMaterial->texture0->bind();
Anakin's avatar
Anakin committed
119
			tmp_transparent = m_defaultMaterial->transparent;
Anakin's avatar
Anakin committed
120
		}
Anakin's avatar
Anakin committed
121
122
123
		// Set model matrix
		program->setUniformValue("m_matrix", it.modelMatrix);

124
125
126
		// Set normal matrix
		program->setUniformValue("n_matrix", (normMatrix * it.modelMatrix).normalMatrix());

Anakin's avatar
Anakin committed
127
		// set some more values
Anakin's avatar
Anakin committed
128
		program->setUniformValue("b_transparent", tmp_transparent);
Anakin's avatar
Anakin committed
129
		program->setUniformValue("b_specular", tmp_specular);
Anakin's avatar
Anakin committed
130

Anakin's avatar
Anakin committed
131
132
133
134
		// set some material attributes
		program->setUniformValue("materialShininess", shininess);
		program->setUniformValue("materialSpecularColor", specularColor);

Anakin's avatar
Anakin committed
135
		// Draw cube geometry using indices from VBO 1
Anakin's avatar
Anakin committed
136
		glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint)));
137

Anakin's avatar
Anakin committed
138
	}
139
}
140

141
142
143
144
145
146
147
148
149
void GeometryEngine::loadFile(QString filePath)
{
	// cleanup old stuff and recreate buffers
	clearData();
	m_arrayBuf.create();
	m_indexBuf.create();

	//reset view
	emit requestResetView();
150
	OutputDevice::getInstance()->print("loading file..", 0);
151
152
153
154
155
156
157
158

	try
	{
		QVector<Model*>* models;
		QVector<VertexData> vertexData;
		QVector<GLuint> indexData;

		// open file and get the information
159
		MshFile file(filePath);
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

		models = file.getModels();
		m_materials = file.getMaterials();
		m_boundings = file.getBoundingBox();

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

				// add offset to indices, no need to do it for the first one (maybe it's very big)
				if (vertexOffset != 0)
					for (auto& it : segmentIterator->indices)
						it += vertexOffset;

				// save data
				vertexData += segmentIterator->vertices;
				indexData += segmentIterator->indices;

				if (segmentIterator->textureIndex < (unsigned) m_materials->size() && m_materials->at(segmentIterator->textureIndex).transparent)
					m_drawList.push_back(new_info);
				else
					m_drawList.push_front(new_info);

				// update offset
				indexOffset += new_info.size;
				vertexOffset += segmentIterator->vertices.size();
			}
		}

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

		emit requestUpdate();
209
		OutputDevice::getInstance()->print("done..", 0);
Anakin's avatar
Anakin committed
210
		OutputDevice::getInstance()->setFileInfo(filePath.right(filePath.size() - filePath.lastIndexOf(QRegExp("/|\\\\")) - 1), m_materials, vertexData.size(), indexData.size() / 3);
211
212
213
214
	}
	catch (std::invalid_argument e)
	{
		clearData();
215
		OutputDevice::getInstance()->print(QString(e.what()), 2);
216
217
218
	}
}