parent
a99effbeb6
commit
8d1c374b0f
17 changed files with 357 additions and 72 deletions
@ -0,0 +1,11 @@ |
|||||||
|
#version 330 core |
||||||
|
|
||||||
|
out vec4 FragColor; |
||||||
|
|
||||||
|
in vec2 texCoord; |
||||||
|
|
||||||
|
uniform sampler2D quadTexture; |
||||||
|
|
||||||
|
void main() { |
||||||
|
FragColor = texture(quadTexture, texCoord); |
||||||
|
} |
@ -1,6 +1,8 @@ |
|||||||
<RCC> |
<RCC> |
||||||
<qresource prefix="/shaders/"> |
<qresource prefix="/shaders/"> |
||||||
<file>vertex.glsl</file> |
<file>vertex_pendula.glsl</file> |
||||||
<file>fragment.glsl</file> |
<file>fragment_pendula.glsl</file> |
||||||
|
<file>vertex_quad.glsl</file> |
||||||
|
<file>fragment_quad.glsl</file> |
||||||
</qresource> |
</qresource> |
||||||
</RCC> |
</RCC> |
@ -0,0 +1,11 @@ |
|||||||
|
#version 330 core |
||||||
|
|
||||||
|
layout (location = 0) in vec2 vPos; |
||||||
|
layout (location = 1) in vec2 vTex; |
||||||
|
|
||||||
|
out vec2 texCoord; |
||||||
|
|
||||||
|
void main() { |
||||||
|
gl_Position = vec4(vPos, 0, 1); |
||||||
|
texCoord = vTex; |
||||||
|
} |
@ -0,0 +1,177 @@ |
|||||||
|
#include "Overlay.h" |
||||||
|
#include "FPS.h" |
||||||
|
#include <QPainter> |
||||||
|
#include <QOpenGLShaderProgram> |
||||||
|
#include "Simulation.h" |
||||||
|
#include <iostream> |
||||||
|
#include <QOpenGLTexture> |
||||||
|
#include <sstream> |
||||||
|
#include <iomanip> |
||||||
|
|
||||||
|
Overlay::Overlay(Simulation * simulation) : simulation(simulation) { |
||||||
|
fps = new FPS; |
||||||
|
fps->setUpdateInterval(500); |
||||||
|
} |
||||||
|
|
||||||
|
void Overlay::init() { |
||||||
|
initializeOpenGLFunctions(); |
||||||
|
|
||||||
|
program = new QOpenGLShaderProgram; |
||||||
|
program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vertex_quad.glsl"); |
||||||
|
program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fragment_quad.glsl"); |
||||||
|
program->link(); |
||||||
|
|
||||||
|
float quadVertices[] = { |
||||||
|
-1, 1, 0, 1, // top left
|
||||||
|
-1, -1, 0, 0, // bottom left
|
||||||
|
1, -1, 1, 0, // bottom right
|
||||||
|
1, 1, 1, 1 // top right
|
||||||
|
}; |
||||||
|
|
||||||
|
GLuint indices[] = { |
||||||
|
0, 1, 2, 2, 3, 0 |
||||||
|
}; |
||||||
|
|
||||||
|
glGenVertexArrays(1, &VAO); |
||||||
|
glBindVertexArray(VAO); |
||||||
|
|
||||||
|
GLuint VBO; |
||||||
|
glGenBuffers(1, &VBO); |
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO); |
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW); |
||||||
|
|
||||||
|
GLuint EBO; |
||||||
|
glGenBuffers(1, &EBO); |
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); |
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); |
||||||
|
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), nullptr); |
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid*) (2 * sizeof(float))); |
||||||
|
glEnableVertexAttribArray(0); |
||||||
|
glEnableVertexAttribArray(1); |
||||||
|
|
||||||
|
glBindVertexArray(0); |
||||||
|
} |
||||||
|
|
||||||
|
void Overlay::draw() { |
||||||
|
int w = viewportSize.width(); |
||||||
|
int h = (viewportSize.height() - simulationRect.height()) / 2; |
||||||
|
|
||||||
|
// Top HUD with Energy Plot
|
||||||
|
{ |
||||||
|
glViewport(0, viewportSize.height() - h, w, h); |
||||||
|
|
||||||
|
QImage hud(w, h, QImage::Format_RGBA8888); |
||||||
|
hud.fill(Qt::transparent); |
||||||
|
|
||||||
|
QPainter p(&hud); |
||||||
|
p.setRenderHints(QPainter::Antialiasing); |
||||||
|
p.setPen(Qt::white); |
||||||
|
auto font = p.font(); |
||||||
|
font.setPixelSize(15); |
||||||
|
p.setFont(font); |
||||||
|
|
||||||
|
auto m = p.fontMetrics(); |
||||||
|
|
||||||
|
double pot = simulation->potentialEnergy; |
||||||
|
double kin = simulation->kineticEnergy; |
||||||
|
double total = pot + kin; |
||||||
|
|
||||||
|
QColor empty(50, 50, 50); |
||||||
|
QColor full(80, 80, 80); |
||||||
|
|
||||||
|
// Total energy bar
|
||||||
|
{ |
||||||
|
double lossPercentage = (1 - total / energyLimit) * 100; |
||||||
|
|
||||||
|
std::stringstream text; |
||||||
|
text << std::fixed << std::setprecision(0) << "Total Energy: " << total << " J"; |
||||||
|
text << " --- "; |
||||||
|
text << "Loss: " << std::setprecision(1) << lossPercentage << " %"; |
||||||
|
QString totalText = QString::fromStdString(text.str()); |
||||||
|
|
||||||
|
int x = int(total / energyLimit * w); |
||||||
|
|
||||||
|
p.fillRect(0, 0, w, h / 2, empty); |
||||||
|
p.fillRect(0, 0, x, h / 2, full); |
||||||
|
p.drawLine(x, 0, x, h / 2); |
||||||
|
p.drawText(0, 0, w, h / 2, Qt::AlignCenter | Qt::AlignVCenter, totalText); |
||||||
|
} |
||||||
|
|
||||||
|
// Split energy bar
|
||||||
|
{ |
||||||
|
int potX = total == 0 ? int(0.5 * w) : int(pot / total * w); |
||||||
|
p.fillRect(0, h / 2, w, h / 2, empty); |
||||||
|
p.fillRect(0, h / 2, potX, h / 2, full); |
||||||
|
|
||||||
|
std::stringstream text; |
||||||
|
text << std::fixed << std::setprecision(0) << "Potential: " << pot << " J"; |
||||||
|
QString potText = QString::fromStdString(text.str()); |
||||||
|
|
||||||
|
text = std::stringstream(); |
||||||
|
text << std::fixed << std::setprecision(0) << "Kinetic: " << kin << " J"; |
||||||
|
QString kinText = QString::fromStdString(text.str()); |
||||||
|
|
||||||
|
int textWidth1 = m.horizontalAdvance(potText); |
||||||
|
int textWidth2 = m.horizontalAdvance(kinText); |
||||||
|
int x1 = (w - textWidth1) / 4; |
||||||
|
int x2 = (w - textWidth2) / 4 * 3; |
||||||
|
|
||||||
|
p.drawLine(potX, h / 2, potX, h); |
||||||
|
p.drawText(x1, h / 2, textWidth1, h / 2, Qt::AlignCenter | Qt::AlignVCenter, potText); |
||||||
|
p.drawText(x2, h / 2, textWidth2, h / 2, Qt::AlignCenter | Qt::AlignVCenter, kinText); |
||||||
|
} |
||||||
|
|
||||||
|
p.drawLine(0, 0, w, 0); |
||||||
|
p.drawLine(0, h / 2, w, h / 2); |
||||||
|
p.drawLine(0, h, w, h); |
||||||
|
|
||||||
|
drawTexture(&hud); |
||||||
|
} |
||||||
|
|
||||||
|
// Bottom HUD with FPS and UPS
|
||||||
|
{ |
||||||
|
glViewport(0, 0, w, h); |
||||||
|
|
||||||
|
QImage hud(w, h, QImage::Format_RGBA8888); |
||||||
|
|
||||||
|
// Background
|
||||||
|
hud.fill(Qt::transparent); |
||||||
|
|
||||||
|
QPainter p(&hud); |
||||||
|
p.setRenderHints(QPainter::Antialiasing); |
||||||
|
|
||||||
|
// FPS
|
||||||
|
{ |
||||||
|
p.setPen(Qt::white); |
||||||
|
auto font = p.font(); |
||||||
|
font.setPixelSize(15); |
||||||
|
p.setFont(font); |
||||||
|
fps->newFrame(); |
||||||
|
std::stringstream text; |
||||||
|
text << "FPS: " << fps->current << "\n"; |
||||||
|
text << "UPS: " << simulation->ups->current; |
||||||
|
p.drawText(0, 0, 100, h, Qt::AlignBottom | Qt::AlignLeft, QString::fromStdString(text.str())); |
||||||
|
} |
||||||
|
drawTexture(&hud); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Overlay::resize(QSize newViewportSize, QRect newSimulationRect) { |
||||||
|
viewportSize = newViewportSize; |
||||||
|
simulationRect = newSimulationRect; |
||||||
|
} |
||||||
|
|
||||||
|
void Overlay::drawTexture(QImage *image) { |
||||||
|
glBindVertexArray(VAO); |
||||||
|
program->bind(); |
||||||
|
|
||||||
|
QOpenGLTexture texture(image->mirrored()); |
||||||
|
texture.bind(); |
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
void Overlay::fetchEnergyLimit() { |
||||||
|
energyLimit = simulation->kineticEnergy + simulation->potentialEnergy; |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
#include <QRect> |
||||||
|
|
||||||
|
#include <QOpenGLExtraFunctions> |
||||||
|
|
||||||
|
class QOpenGLWidget; |
||||||
|
class FPS; |
||||||
|
class QOpenGLShaderProgram; |
||||||
|
class QOpenGLTexture; |
||||||
|
class Simulation; |
||||||
|
|
||||||
|
class Overlay : public QObject, protected QOpenGLExtraFunctions { |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
FPS * fps; |
||||||
|
QSize viewportSize; |
||||||
|
QRect simulationRect; |
||||||
|
QOpenGLShaderProgram * program; |
||||||
|
GLuint VAO; |
||||||
|
void drawTexture(QImage *image); |
||||||
|
Simulation * simulation; |
||||||
|
double energyLimit = 0; |
||||||
|
public slots: |
||||||
|
void fetchEnergyLimit(); |
||||||
|
public: |
||||||
|
explicit Overlay(Simulation *); |
||||||
|
void init(); |
||||||
|
void draw(); |
||||||
|
void resize(QSize newViewportSize, QRect newSimulationRect); |
||||||
|
}; |
Loading…
Reference in new issue