qtk/src/meshrenderer.cpp

187 lines
5.4 KiB
C++
Raw Normal View History

2021-09-03 16:56:57 +00:00
/*##############################################################################
## Author: Shaun Reed ##
2022-03-06 16:54:05 +00:00
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
2021-09-03 16:56:57 +00:00
## About: MeshRenderer class for quick object creation and drawing ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <QImageReader>
#include <abstractscene.h>
2021-09-03 16:56:57 +00:00
#include <meshrenderer.h>
#include <texture.h>
2021-09-03 16:56:57 +00:00
using namespace Qtk;
2021-09-03 16:56:57 +00:00
// Static QHash that holds all MeshRenderer instances using their mName as keys
Qtk::MeshRenderer::MeshManager Qtk::MeshRenderer::sInstances;
2021-09-03 16:56:57 +00:00
2022-11-24 22:26:53 +00:00
MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) :
Object(name, shape), mVertexShader(":/multi-color.vert"),
mFragmentShader(":/multi-color.frag"), mDrawType(GL_TRIANGLES) {
2021-09-03 16:56:57 +00:00
mShape = Shape(shape);
init();
sInstances.insert(name, this);
}
2022-11-24 22:26:53 +00:00
MeshRenderer::~MeshRenderer() {
2021-09-03 16:56:57 +00:00
sInstances.remove(mName);
}
// Static member function to retrieve instances of MeshRenderers
2022-11-24 22:26:53 +00:00
MeshRenderer * MeshRenderer::getInstance(const QString & name) {
return sInstances[name];
}
2021-09-03 16:56:57 +00:00
/*******************************************************************************
* Public Member Functions
******************************************************************************/
2022-11-24 22:26:53 +00:00
void MeshRenderer::init() {
if(mVAO.isCreated()) {
mVAO.destroy();
}
if(mProgram.isLinked()) {
mProgram.removeAllShaders();
}
if(mVBO.isCreated()) {
mVBO.destroy();
}
2021-09-03 16:56:57 +00:00
mVAO.create();
mVAO.bind();
mProgram.create();
2022-11-24 22:26:53 +00:00
mProgram.addShaderFromSourceFile(
QOpenGLShader::Vertex, mVertexShader.c_str());
mProgram.addShaderFromSourceFile(
QOpenGLShader::Fragment, mFragmentShader.c_str());
2021-09-03 16:56:57 +00:00
mProgram.link();
mProgram.bind();
mVBO.create();
mVBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mVBO.bind();
// Combine position and color data into one vector, allowing us to use one VBO
Vertices combined;
2022-11-24 22:26:53 +00:00
combined.reserve(getVertices().size() + getColors().size());
combined.insert(combined.end(), getVertices().begin(), getVertices().end());
combined.insert(combined.end(), getColors().begin(), getColors().end());
2021-09-03 16:56:57 +00:00
2022-11-24 22:26:53 +00:00
mVBO.allocate(combined.data(), combined.size() * sizeof(combined[0]));
2021-09-03 16:56:57 +00:00
// Enable position attribute
mProgram.enableAttributeArray(0);
2022-11-24 22:26:53 +00:00
mProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(QVector3D));
2021-09-03 16:56:57 +00:00
// Enable color attribute, setting offset to total size of vertices()
mProgram.enableAttributeArray(1);
2022-11-24 22:26:53 +00:00
mProgram.setAttributeBuffer(
1, GL_FLOAT, getVertices().size() * sizeof(getVertices()[0]), 3,
sizeof(QVector3D));
2021-09-03 16:56:57 +00:00
mVBO.release();
mProgram.release();
mVAO.release();
}
2022-11-24 22:26:53 +00:00
void MeshRenderer::draw() {
bindShaders();
2021-09-03 16:56:57 +00:00
mVAO.bind();
2022-11-24 22:26:53 +00:00
if(mTexture.hasTexture()) {
mTexture.getOpenGLTexture().bind();
2021-09-03 16:56:57 +00:00
}
// TODO: Automate uniforms some other way
setUniformMVP();
2022-11-24 22:26:53 +00:00
if(mShape.mDrawMode == QTK_DRAW_ARRAYS) {
glDrawArrays(mDrawType, 0, getVertices().size());
} else if(
mShape.mDrawMode == QTK_DRAW_ELEMENTS
|| mShape.mDrawMode == QTK_DRAW_ELEMENTS_NORMALS) {
glDrawElements(
mDrawType, mShape.mIndices.size(), GL_UNSIGNED_INT,
mShape.mIndices.data());
2021-09-03 16:56:57 +00:00
}
2022-11-24 22:26:53 +00:00
if(mTexture.hasTexture()) {
mTexture.getOpenGLTexture().release();
2021-09-03 16:56:57 +00:00
}
mVAO.release();
2022-11-24 22:26:53 +00:00
releaseShaders();
2021-09-03 16:56:57 +00:00
}
2022-11-24 22:26:53 +00:00
void MeshRenderer::setShaders(
const std::string & vert, const std::string & frag) {
2021-09-03 16:56:57 +00:00
mVertexShader = vert;
mFragmentShader = frag;
2022-11-24 22:26:53 +00:00
init();
2021-09-03 16:56:57 +00:00
}
2022-11-24 22:26:53 +00:00
void MeshRenderer::setUniformMVP(
const char * model, const char * view, const char * projection) {
ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(projection, Scene::Projection());
mProgram.setUniformValue(view, Scene::View());
2021-09-03 16:56:57 +00:00
mProgram.setUniformValue(model, mTransform.toMatrix());
}
2022-11-24 22:26:53 +00:00
void MeshRenderer::setColor(const QVector3D & color) {
if(mShape.mColors.empty()) {
for(const auto & vertex : mShape.getVertices()) {
2021-09-03 16:56:57 +00:00
mShape.mColors.push_back(color);
}
2022-11-24 22:26:53 +00:00
} else {
for(int i = 0; i < mShape.getColors().size(); i++) {
2021-09-03 16:56:57 +00:00
mShape.mColors[i] = color;
}
}
}
2022-11-24 22:26:53 +00:00
void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims) {
mVAO.bind();
mNBO.destroy();
mNBO.create();
mNBO.bind();
mNBO.allocate(t.data(), t.size() * sizeof(t[0]));
enableAttributeArray(1);
if(dims == 2) {
setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));
} else if(dims == 3) {
setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
}
mNBO.release();
mVAO.release();
2021-09-03 16:56:57 +00:00
}
2022-11-24 22:26:53 +00:00
void MeshRenderer::reallocateNormals(const Normals & n, unsigned dims) {
// TODO: Store state to track if buffer objects are bound
mVAO.bind();
mNBO.destroy();
mNBO.create();
mNBO.bind();
mNBO.allocate(n.data(), n.size() * sizeof(n[0]));
enableAttributeArray(1);
if(dims == 2) {
setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));
} else if(dims == 3) {
setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
}
mNBO.release();
mVAO.release();
2021-09-03 16:56:57 +00:00
}
/*******************************************************************************
* Inherited Virtual Member Functions
******************************************************************************/
2022-11-24 22:26:53 +00:00
void MeshRenderer::setShape(const Shape & value) {
2021-09-03 16:56:57 +00:00
Object::setShape(value);
init();
}