GeometryEngine.cpp 5.03 KB
Newer Older
1 2 3 4 5
#include "..\Header\GeometryEngine.h"

#include <QVector2D>
#include <QVector3D>

Anakin's avatar
Anakin committed
6

7 8
struct VertexData
{
Anakin's avatar
Anakin committed
9 10
	QVector3D position;
	QVector2D texCoord;
11 12 13
};

GeometryEngine::GeometryEngine()
Anakin's avatar
Anakin committed
14 15
	: indexBuf(QOpenGLBuffer::IndexBuffer)
	, texture(Q_NULLPTR)
16
{
Anakin's avatar
Anakin committed
17
	initializeOpenGLFunctions();
18

Anakin's avatar
Anakin committed
19 20 21
	// Generate 2 VBOs
	arrayBuf.create();
	indexBuf.create();
22

Anakin's avatar
Anakin committed
23 24
	// Initializes cube geometry and transfers it to VBOs
	initCubeGeometry();
25 26 27 28
}

GeometryEngine::~GeometryEngine()
{
Anakin's avatar
Anakin committed
29 30 31
	arrayBuf.destroy();
	indexBuf.destroy();
	delete texture;
32 33 34 35
}

void GeometryEngine::initCubeGeometry()
{
Anakin's avatar
Anakin committed
36 37 38
	// For cube we would need only 8 vertices but we have to
	// duplicate vertex for each face because texture coordinate
	// is different.
39 40 41 42 43 44 45 46 47 48 49 50 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 79 80 81 82 83 84
    VertexData vertices[] = {
        // Vertex data for face 0
        {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(0.0f, 0.0f)},  // v0
        {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D(0.33f, 0.0f)}, // v1
        {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(0.0f, 0.5f)},  // v2
        {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v3

        // Vertex data for face 1
        {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D( 0.0f, 0.5f)}, // v4
        {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.5f)}, // v5
        {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.0f, 1.0f)},  // v6
        {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v7

        // Vertex data for face 2
        {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v8
        {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(1.0f, 0.5f)},  // v9
        {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.66f, 1.0f)}, // v10
        {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(1.0f, 1.0f)},  // v11

        // Vertex data for face 3
        {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v12
        {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(1.0f, 0.0f)},  // v13
        {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v14
        {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(1.0f, 0.5f)},  // v15

        // Vertex data for face 4
        {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.0f)}, // v16
        {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v17
        {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v18
        {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D(0.66f, 0.5f)}, // v19

        // Vertex data for face 5
        {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v20
        {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.66f, 0.5f)}, // v21
        {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v22
        {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.66f, 1.0f)}  // v23
    };

    // Indices for drawing cube faces using triangle strips.
    // Triangle strips can be connected by duplicating indices
    // between the strips. If connecting strips have opposite
    // vertex order then last index of the first strip and first
    // index of the second strip needs to be duplicated. If
    // connecting strips have same vertex order then only last
    // index of the first strip needs to be duplicated.
    GLushort indices[] = {
Anakin's avatar
Anakin committed
85 86 87 88 89 90 91 92 93 94 95 96
		0,1,2,		//vorne (4)
		3,2,1,
		4,5,7,		//rechts (1)
		6,4,7,
		8,9,11,		//hinten (3)*
		8,11,10,
		14,12,13,	//links (6)*
		14,13,15,
		18,16,17,	//unten (5)
		19,18,17,
		23,22,20,	//oben (2)*
		23,20,21
97 98 99 100 101 102 103 104
    };

    // Transfer vertex data to VBO 0
    arrayBuf.bind();
    arrayBuf.allocate(vertices, 24 * sizeof(VertexData));

    // Transfer index data to VBO 1
    indexBuf.bind();
Anakin's avatar
Anakin committed
105 106 107
    indexBuf.allocate(indices, 36 * sizeof(GLushort));

	initTexture();
108 109
}

Anakin's avatar
Anakin committed
110
void GeometryEngine::initTexture()
111
{
Anakin's avatar
Anakin committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	// Load cube.png image
	texture = new QOpenGLTexture(QImage(":images/cube.png").mirrored());

	// Set nearest filtering mode for texture minification
	texture->setMinificationFilter(QOpenGLTexture::Nearest);

	// Set bilinear filtering mode for texture magnification
	texture->setMagnificationFilter(QOpenGLTexture::Linear);

	// Wrap texture coordinates by repeating
	// f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
	texture->setWrapMode(QOpenGLTexture::Repeat);
}

void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
{
	// Tell OpenGL which VBOs to use
	arrayBuf.bind();
	indexBuf.bind();
	texture->bind();

	// Use texture unit 0 which contains cube.png
	program->setUniformValue("texture", 0);
135

Anakin's avatar
Anakin committed
136 137
	// Offset for position
	quintptr offset = 0;
138

Anakin's avatar
Anakin committed
139 140 141 142
	// 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));
143

Anakin's avatar
Anakin committed
144 145
	// Offset for texture coordinate
	offset += sizeof(QVector3D);
146

Anakin's avatar
Anakin committed
147 148 149 150
	// 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));
151

Anakin's avatar
Anakin committed
152 153
	// Draw cube geometry using indices from VBO 1
	glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
154
}