#include "badprogOpenglWidget.h"
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
#include <QDebug>
#include <QKeyEvent>
#include <QMouseEvent>
#include "input.h"
// badprog.com
// ----------------------------------------------------------------------------
BadprogOpenGLWidget::BadprogOpenGLWidget(QWidget *parent)
: _vbo1_index(QOpenGLBuffer::IndexBuffer)
{
//
_transform.translate(0.0f, 0.0f, -5.0f);
_transform2.translate(-1.0f, 0.0f, -5.0f);
_NUMBER_OF_ELEMENTS = 4;
_NUMBER_OF_ELEMENTS2 = 4;
_stateRotate = true;
_firstRound = true;
_NUMBER_OF_VAO = 10;
_counter = 0;
//
setFocusPolicy(Qt::StrongFocus);
}
// ----------------------------------------------------------------------------
BadprogOpenGLWidget::~BadprogOpenGLWidget() {
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::initializeGL() {
//
initializeOpenGLFunctions();
//
glEnable(GL_DEPTH_TEST);
glClearColor(0.5f, 0.4f, 0.3f, 0.5f);
glEnable(GL_PROGRAM_POINT_SIZE);
glLineWidth(2);
// ========================================================================
//
// Program 1 - Cube color
//
// ========================================================================
initProgramColor();
// Array of vertex
StructVertex arrayVertex[] = {
// First triangle // Color // texture
{ QVector3D(-0.5f, -0.5f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f), QVector2D(0.0f, 0.0f) }, // 0
{ QVector3D( 0.5f, -0.5f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f), QVector2D(1.0f, 0.0f) }, // 1
{ QVector3D(-0.5f, 0.5f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f), QVector2D(0.0f, 1.0f) }, // 2
{ QVector3D( 0.5f, 0.5f, 0.5f), QVector3D(1.0f, 0.5f, 0.1f), QVector2D(1.0f, 1.0f) }, // 3
{ QVector3D(-0.5f, -0.5f, -0.5f), QVector3D(1.0f, 0.0f, 0.0f), QVector2D(0.0f, 0.0f) }, // 4
{ QVector3D( 0.5f, -0.5f, -0.5f), QVector3D(0.0f, 1.0f, 0.0f), QVector2D(1.0f, 0.0f) }, // 5
{ QVector3D(-0.5f, 0.5f, -0.5f), QVector3D(0.0f, 0.0f, 1.0f), QVector2D(0.0f, 1.0f) }, // 6
{ QVector3D( 0.5f, 0.5f, -0.5f), QVector3D(1.0f, 0.5f, 0.1f), QVector2D(1.0f, 1.0f) }, // 7
};
// Array index
GLushort arrayIndex[] = {
0, 1, 2, 3,
3, 1, 7, 5,
5, 4, 7, 6,
6, 2, 7, 3,
3, 2, 6, 0,
4, 5, 1, 0
};
_NUMBER_OF_ELEMENTS = sizeof(arrayIndex)/ sizeof(GLushort);
// ------------------------------------------
// VAO 1
// ------------------------------------------
_vao1.create();
_vao1.bind();
// Buffer 1
_vbo1_position.create();
_vbo1_position.bind();
_vbo1_position.setUsagePattern(QOpenGLBuffer::StreamDraw);
_vbo1_position.allocate(arrayVertex, sizeof (StructVertex) * _NUMBER_OF_ELEMENTS);
// VBO 1
int bpOffset = 0; // offset position in the array
int bpTuple = 3; // number of element in QVector3D
int bpStride = sizeof (StructVertex); // number of elements to skip before the next position element in the whole line (position, color and texture --> QVector3D, QVector3D, QVector2D) inthe array
// program
_program1->enableAttributeArray(_attribute1_position);
_program1->setAttributeBuffer(_attribute1_position, GL_FLOAT, bpOffset, bpTuple, bpStride);
//
// Buffer 2
_vbo1_index.create();
_vbo1_index.bind();
// _vbo1_index.allocate(arrayIndex, sizeof (GLushort) * 4);
_vbo1_index.allocate(arrayIndex, sizeof (GLushort) * _NUMBER_OF_ELEMENTS);
// VBO 2 (index)
bpOffset += sizeof (QVector3D); // offset color in the array
bpTuple = 3; // number of elements in the QVector3D in the array
// program
_program1->enableAttributeArray(_attribute1_color);
_program1->setAttributeBuffer(_attribute1_color, GL_FLOAT, bpOffset, bpTuple, bpStride);
// Release.
_vbo1_position.release();
_vbo1_index.release();
_vao1.release();
StructVertex arrayVertex2[] = {
// First triangle // Color // texture
{ QVector3D(-0.5f, -0.5f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f), QVector2D(0.0f, 0.0f) }, // 0
{ QVector3D(0.0f, 0.5f, -0.5f), QVector3D(1.0f, 0.5f, 0.1f), QVector2D(1.0f, 1.0f) }, // 1
{ QVector3D(0.5f, 0.5f, 0.5f), QVector3D(0.2f, 0.8f, 1.0f), QVector2D(0.0f, 1.0f) }, // 2
{ QVector3D(-0.7f, -0.7f, 0.5f), QVector3D(0.5f, 0.0f, 0.0f), QVector2D(0.0f, 0.0f) }, // 3
{ QVector3D(-0.1f, -0.5f, 0.5f), QVector3D(0.5f, 0.5f, 0.1f), QVector2D(1.0f, 1.0f) }, // 4
{ QVector3D(0.7f, 0.7f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f), QVector2D(0.0f, 1.0f) }, // 5
{ QVector3D(-0.3f, -0.3f, 0.5f), QVector3D(0.3f, 0.2f, 0.0f), QVector2D(0.0f, 0.0f) }, // 6
{ QVector3D(-0.8f, -0.8f, -0.5f), QVector3D(0.4f, 0.6f, 0.1f), QVector2D(1.0f, 1.0f) }, // 7
{ QVector3D(0.6f, 0.6f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f), QVector2D(0.0f, 1.0f) }, // 8
};
//
GLushort arrayIndex2[] = { 0, 1, 1, 2, 2, 0 };
GLushort arrayIndex3[] = { 3, 4, 4, 5, 5, 3 };
GLushort arrayIndex4[] = { 1, 8, 8, 4, 4, 1 };
//
_NUMBER_OF_ELEMENTS2 = sizeof(arrayIndex2)/ sizeof(GLushort);
//
createVAO(arrayVertex2, arrayIndex2[0], 4);
createVAO(arrayVertex2, arrayIndex3[0], 5);
createVAO(arrayVertex2, arrayIndex4[0], 10);
// ========================================================================
//
// Program 2 - Cube texture
//
// ========================================================================
initProgramTexture();
// VAO 1
_vao1.bind();
// VBO 1 - Position
_vbo1_position.bind();
// VBO 1
bpOffset = 0; // offset position in the array
bpTuple = 3; // number of elements in the QVector3D in the array
bpStride = sizeof (StructVertex); // number of elements to skip before the next position element in the whole line (position, color and texture --> QVector3D, QVector3D, QVector2D) inthe array
// program
_program2->enableAttributeArray(_attribute2_position);
_program2->setAttributeBuffer(_attribute2_position, GL_FLOAT, bpOffset, bpTuple, bpStride);
// VBO 1 - Index
_vbo1_index.bind();
// VBO 1 - Textures
bpOffset += sizeof (QVector3D) * 2; // we jump from offset 0 to offset (position + color vectors)
bpTuple = 2; // number of elements in the texture QVector2D in the array
// program
_program2->enableAttributeArray(_attribute2_texture);
_program2->setAttributeBuffer(_attribute2_texture, GL_FLOAT, bpOffset, bpTuple, bpStride);
//
_texture = new QOpenGLTexture(QImage(":/wood3").mirrored());
// Release.
_vbo1_position.release();
_vbo1_index.release();
_vao1.release();
_program2->release();
//
initTimer();
//
_appareanceType = APPAREANCE_TYPE_COLOR;
_vector3DForTranslation = QVector3D(0.0f, 0.0f, -4.0f); // default camera position
//
QObject::connect(this, &QOpenGLWidget::frameSwapped, this, &BadprogOpenGLWidget::slotFrameSwapped);
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::createVAO(StructVertex arrayVertexFromLoop[], GLushort &arrayIndex2, int numberToLoop) {
//
if (_firstRound) {
_counter = 0;
_firstRound = false;
} else {
numberToLoop += _counter;
}
//
while (_counter < numberToLoop) {
// Fills the vector of VAOs with create() and bind() calls.
_vectorOfVaos.push_back(new QOpenGLVertexArrayObject());
_vectorOfVaos.at(_counter)->create();
_vectorOfVaos.at(_counter)->bind();
//
// Creates buffer 1: the VBO Position.
//
_vectorOfVboPositions.push_back(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
_vectorOfVboPositions.at(_counter)->create();
_vectorOfVboPositions.at(_counter)->bind();
float x;
float y;
float newSize = _counter;
if (_counter > 10) {
newSize = _counter / 10;
}
x = arrayVertexFromLoop->elementPosition.x() + (_counter / 20);
y = arrayVertexFromLoop->elementPosition.y() + (_counter / 20);
arrayVertexFromLoop[0].elementPosition.setX(x);
arrayVertexFromLoop[0].elementPosition.setY(y);
arrayVertexFromLoop[3].elementPosition.setX(x);
arrayVertexFromLoop[3].elementPosition.setY(y);
_vectorOfVboPositions.at(_counter)->allocate(arrayVertexFromLoop, sizeof(StructVertex) * _NUMBER_OF_ELEMENTS2);
// VBO 1: Where is the attribute "position" in the array.
int bpOffset = 0; // offset position in the array
int bpTuple = 3; // number of element in QVector3D
int bpStride = sizeof (StructVertex); // number of elements to skip before the next position element in the whole line (position, color and texture --> QVector3D, QVector3D, QVector2D) inthe array
// program
_program1->enableAttributeArray(_attribute1_position);
_program1->setAttributeBuffer(_attribute1_position, GL_FLOAT, bpOffset, bpTuple, bpStride);
// VBO 1: Where is the attribute "color" in the array.
bpOffset += sizeof (QVector3D); // offset color in the array
bpTuple = 3; // number of elements in the QVector3D in the array
// program
_program1->enableAttributeArray(_attribute1_color);
_program1->setAttributeBuffer(_attribute1_color, GL_FLOAT, bpOffset, bpTuple, bpStride);
//
// Creates buffer 2: the VBO Index.
//
_vectorOfVboIndices.push_back(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer));
_vectorOfVboIndices.at(_counter)->create();
_vectorOfVboIndices.at(_counter)->bind();
_vectorOfVboIndices.at(_counter)->allocate(&arrayIndex2, sizeof (GLushort) * _NUMBER_OF_ELEMENTS2);
++_counter;
}
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::initTimer() {
//
_stateTimer = true;
//
_timer = new QTimer(this);
//
QObject::connect(_timer, &QTimer::timeout, this, &BadprogOpenGLWidget::slotUpdateTimer);
_timer->start(1);
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::retrieveAppearence(int appareance) {
//
if (APPAREANCE_TYPE_COLOR == appareance) {
initProgramColor();
} else if (APPAREANCE_TYPE_TEXTURE == appareance) {
initProgramTexture();
} else {
qDebug() << "Problem in the place";
}
//
Input::reset();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::initProgramColor() {
//
_appareanceType = APPAREANCE_TYPE_COLOR;
// Program.
_program1 = new QOpenGLShaderProgram(this);
_program1->addShaderFromSourceFile(QOpenGLShader::Vertex, ":vertex_color");
_program1->addShaderFromSourceFile(QOpenGLShader::Fragment, ":fragment_color");
// Linking.
_program1->link();
// Attributes.
_attribute1_position = _program1->attributeLocation("layoutPosition");
_attribute1_color = _program1->attributeLocation("layoutColor");
// uniform
_uniformMatrixId_model = _program1->uniformLocation("model");
// uniform
_uniformMatrixId_view = _program1->uniformLocation("view");
// uniform projection / cameraToView
_uniformMatrixId_projection = _program1->uniformLocation("projection");
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::initProgramTexture() {
//
_appareanceType = APPAREANCE_TYPE_TEXTURE;
// Program.
_program2 = new QOpenGLShaderProgram(this);
_program2->addShaderFromSourceFile(QOpenGLShader::Vertex, ":vertex_texture");
_program2->addShaderFromSourceFile(QOpenGLShader::Fragment, ":fragment_texture");
// Linking.
_program2->link();
// Attributes.
_attribute2_position = _program2->attributeLocation("layoutPosition");
_attribute2_texture = _program2->attributeLocation("layoutTexture");
// uniform
_uniformMatrixId_model = _program2->uniformLocation("model");
// uniform
_uniformMatrixId_view = _program2->uniformLocation("view");
// uniform projection / cameraToView
_uniformMatrixId_projection = _program2->uniformLocation("projection");
}
// ----------------------------------------------------------------------------
bool BadprogOpenGLWidget::changeTimerState() {
//
if (_stateTimer) {
_timer->stop();
} else {
_timer->start(1);
}
//
_stateTimer = !_stateTimer;
//
return _stateTimer;
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::slotUpdateTimer() {
QOpenGLWidget::update();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::resizeGL(int width, int height) {
_projection.setToIdentity();
_projection.perspective(60.0f, width / float(height), 0.1f, 100.0f);
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::keyPressEvent(QKeyEvent *event) {
//
if (event->key() == Qt::Key_Escape) {
close();
} else if (event->key() == Qt::Key_W) {
_key = event->key();
} else if (event->key() == Qt::Key_S) {
_key = event->key();
} else if (event->key() == Qt::Key_A) {
_key = event->key();
} else if (event->key() == Qt::Key_D) {
_key = event->key();
} else if (event->key() == Qt::Key_E) {
_key = event->key();
} else if (event->key() == Qt::Key_Q) {
_key = event->key();
} else {
QWidget::keyPressEvent(event);
}
//
if (event->isAutoRepeat())
{
event->ignore();
}
else
{
Input::registerKeyPress(event->key());
}
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::keyReleaseEvent(QKeyEvent *event)
{
if (event->isAutoRepeat())
{
event->ignore();
}
else
{
Input::registerKeyRelease(event->key());
}
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::mousePressEvent(QMouseEvent *event)
{
Input::registerMousePress(event->button());
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::mouseReleaseEvent(QMouseEvent *event)
{
Input::registerMouseRelease(event->button());
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::slotFrameSwapped() {
//
Input::update();
//
static const float transSpeed = 0.09f; // keyboard
static const float rotSpeed = 0.05f; // mouse
// Camera Transformation
if (Input::buttonPressed(Qt::LeftButton)) {
// Handle rotations
_camera.rotate(-rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp);
_camera.rotate(-rotSpeed * Input::mouseDelta().y(), _camera.right());
}
// Handle translations
QVector3D translation;
if (Input::keyPressed(Qt::Key_W)) {
translation += _camera.forward();
}
if (Input::keyPressed(Qt::Key_S)) {
translation -= _camera.forward();
}
if (Input::keyPressed(Qt::Key_A)) {
translation -= _camera.right();
}
if (Input::keyPressed(Qt::Key_D)) {
translation += _camera.right();
}
if (Input::keyPressed(Qt::Key_Q)) {
translation -= _camera.up();
}
if (Input::keyPressed(Qt::Key_E)) {
translation += _camera.up();
}
// Resets the camera with:
// rotation angle = 0 and position 0, 0, 0 (x, y, z)
// translation = 0, 0, 0 (x, y, z).
if (Input::keyPressed(Qt::Key_P)){
resetCamera();
}
_camera.translate(transSpeed * translation);
//
if (_stateRotate) {
_transform.rotate(1.0f, QVector3D(0.4f, 0.3f, 0.3f));
_transform2.rotate(-1.0f, QVector3D(0.9f, 0.1f, 0.7f));
} else {
_transform.rotate(0.0f, QVector3D(0.0f, 0.0f, 0.0f));
_transform2.rotate(0.0f, QVector3D(0.0f, 0.0f, 0.0f));
}
// Schedule a redraw
QOpenGLWidget::update();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::rotateSwitcher(bool state) {
//
_stateRotate = state;
//
Input::reset();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::resetCamera() {
_camera.setRotation(0.0f, QVector3D(0.0f, 0.0f, 0.0f));
_camera.setTranslation(QVector3D(0.0f, 0.0f, 0.0f));
//
Input::reset();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::resetObject() {
//
_transform.setRotation(0.0f, QVector3D(0.0f, 0.0f, 0.0f));
_transform2.setRotation(0.0f, QVector3D(0.0f, 0.0f, 0.0f));
//
Input::reset();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::resetBoth() {
//
resetCamera();
resetObject();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::managerUniformValue1() {
// projection / cameraToView
_program1->setUniformValue(_uniformMatrixId_projection, _projection);
//
_program1->setUniformValue(_uniformMatrixId_view, _camera.toMatrix());
//
_program1->setUniformValue(_uniformMatrixId_model, _transform.toMatrix());
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::managerUniformValue2() {
// projection / cameraToView
_program1->setUniformValue(_uniformMatrixId_projection, _projection);
//
_program1->setUniformValue(_uniformMatrixId_view, _camera.toMatrix());
//
_program1->setUniformValue(_uniformMatrixId_model, _transform2.toMatrix());
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::paintGL() {
//
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
if (APPAREANCE_TYPE_COLOR == _appareanceType) {
//
_program1->bind();
//
managerUniformValue1();
drawObject1();
//
managerUniformValue2();
drawObject2();
} else if (APPAREANCE_TYPE_TEXTURE == _appareanceType) {
//
_program2->bind();
//
_texture->bind();
//
managerUniformValue1();
drawObject1();
}
//
if (APPAREANCE_TYPE_COLOR == _appareanceType) {
_program1->release();
} else if (APPAREANCE_TYPE_TEXTURE == _appareanceType) {
_texture->release();
_program2->release();
}
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::drawObject1() {
// VAO 1
_vao1.bind();
// VBO 1 - Index
_vbo1_index.bind();
glDrawElements(GL_TRIANGLE_STRIP, _NUMBER_OF_ELEMENTS, GL_UNSIGNED_SHORT, 0);
_vbo1_index.release();
_vao1.release();
}
// ----------------------------------------------------------------------------
void BadprogOpenGLWidget::drawObject2() {
//
int i = 0;
for (auto &element : _vectorOfVaos) {
element->bind();
_vectorOfVboIndices.at(i)->bind();
glDrawElements(GL_LINES, _NUMBER_OF_ELEMENTS2, GL_UNSIGNED_SHORT, 0);
_vectorOfVboIndices.at(i)->release();
++i;
}
}
Add new comment