196 lines
6.2 KiB
C++
196 lines
6.2 KiB
C++
#include "SketchGrid.h"
|
|
#include "ViewportWidget.h"
|
|
#include "Camera.h"
|
|
#include <QOpenGLContext>
|
|
#include <QOpenGLExtraFunctions>
|
|
#include <QOpenGLShaderProgram>
|
|
#include <QPainter>
|
|
#include <QVector>
|
|
|
|
namespace {
|
|
struct GridParams {
|
|
float minorIncrement;
|
|
float majorIncrement;
|
|
int gridSize;
|
|
};
|
|
|
|
GridParams getGridParams(float distance)
|
|
{
|
|
if (distance > 500.0f) {
|
|
return { 20.0f, 100.0f, 1000 };
|
|
} else if (distance > 250.0f) {
|
|
return { 10.0f, 50.0f, 1000 };
|
|
} else if (distance > 50.0f) {
|
|
return { 5.0f, 25.0f, 1000 };
|
|
} else if (distance > 10.0f) {
|
|
return { 1.0f, 5.0f, 100 };
|
|
} else { // zoomed in
|
|
return { 0.2f, 1.0f, 10 };
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
SketchGrid::SketchGrid(ViewportWidget* viewport) : m_viewport(viewport)
|
|
{
|
|
}
|
|
|
|
SketchGrid::~SketchGrid()
|
|
{
|
|
}
|
|
|
|
void SketchGrid::initializeGL()
|
|
{
|
|
initializeOpenGLFunctions();
|
|
|
|
m_vao.create();
|
|
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
|
|
|
|
m_vbo.create();
|
|
m_vbo.bind();
|
|
m_vbo.allocate(nullptr, 0); // Allocate when drawing
|
|
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
|
|
|
|
m_vbo.release();
|
|
}
|
|
|
|
void SketchGrid::paintGL(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
|
{
|
|
GLint previous_vao = 0;
|
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previous_vao);
|
|
|
|
m_vao.bind();
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
drawGridLines(plane, shaderProgram, colorLoc);
|
|
drawAxes(plane, shaderProgram, colorLoc);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
QOpenGLContext::currentContext()->extraFunctions()->glBindVertexArray(previous_vao);
|
|
}
|
|
|
|
void SketchGrid::drawGridLines(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
|
{
|
|
auto params = getGridParams(-m_viewport->camera()->uiCameraDistance());
|
|
const float minorIncrement = params.minorIncrement;
|
|
const int gridSize = params.gridSize;
|
|
|
|
QVector<GLfloat> minorLines;
|
|
QVector<GLfloat> majorLines;
|
|
|
|
int numLines = gridSize / minorIncrement;
|
|
for (int i = -numLines; i <= numLines; ++i) {
|
|
if (i == 0)
|
|
continue;
|
|
|
|
float pos = i * minorIncrement;
|
|
QVector<GLfloat>& current_vector = (i % 5 == 0) ? majorLines : minorLines;
|
|
if (plane == XY) {
|
|
current_vector << pos << 0 << -gridSize << pos << 0 << gridSize;
|
|
current_vector << -gridSize << 0 << pos << gridSize << 0 << pos;
|
|
} else if (plane == XZ) {
|
|
current_vector << pos << -gridSize << 0 << pos << gridSize << 0;
|
|
current_vector << -gridSize << pos << 0 << gridSize << pos << 0;
|
|
} else { // YZ
|
|
current_vector << 0 << pos << -gridSize << 0 << pos << gridSize;
|
|
current_vector << 0 << -gridSize << pos << 0 << gridSize << pos;
|
|
}
|
|
}
|
|
|
|
m_vbo.bind();
|
|
|
|
// Draw minor lines
|
|
shaderProgram->setUniformValue(colorLoc, QVector4D(0.4f, 0.4f, 0.4f, 1.0f));
|
|
glLineWidth(1.0f);
|
|
m_vbo.allocate(minorLines.constData(), minorLines.size() * sizeof(GLfloat));
|
|
glDrawArrays(GL_LINES, 0, minorLines.size() / 3);
|
|
|
|
// Draw major lines
|
|
shaderProgram->setUniformValue(colorLoc, QVector4D(0.6f, 0.6f, 0.6f, 1.0f));
|
|
glLineWidth(1.0f);
|
|
m_vbo.allocate(majorLines.constData(), majorLines.size() * sizeof(GLfloat));
|
|
glDrawArrays(GL_LINES, 0, majorLines.size() / 3);
|
|
}
|
|
|
|
void SketchGrid::drawAxes(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
|
{
|
|
auto params = getGridParams(-m_viewport->camera()->uiCameraDistance());
|
|
const int axisLength = params.gridSize;
|
|
QVector<GLfloat> vertices;
|
|
|
|
glLineWidth(2.0f);
|
|
m_vbo.bind();
|
|
|
|
// X Axis (Red)
|
|
if (plane == XY || plane == XZ) {
|
|
vertices.clear();
|
|
vertices << -axisLength << 0 << 0 << axisLength << 0 << 0;
|
|
shaderProgram->setUniformValue(colorLoc, QVector4D(1.0f, 0.0f, 0.0f, 1.0f));
|
|
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
}
|
|
// Y Axis (Green)
|
|
if (plane == XY || plane == YZ) {
|
|
vertices.clear();
|
|
vertices << 0 << 0 << -axisLength << 0 << 0 << axisLength;
|
|
shaderProgram->setUniformValue(colorLoc, QVector4D(0.0f, 1.0f, 0.0f, 1.0f));
|
|
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
}
|
|
// Z Axis (Blue)
|
|
if (plane == XZ || plane == YZ) {
|
|
vertices.clear();
|
|
vertices << 0 << -axisLength << 0 << 0 << axisLength << 0;
|
|
shaderProgram->setUniformValue(colorLoc, QVector4D(0.0f, 0.0f, 1.0f, 1.0f));
|
|
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
}
|
|
|
|
// Origin dot
|
|
glPointSize(5.0f);
|
|
vertices.clear();
|
|
vertices << 0.0f << 0.0f << 0.0f;
|
|
shaderProgram->setUniformValue(colorLoc, QVector4D(1.0f, 1.0f, 1.0f, 1.0f)); // White
|
|
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
|
glDrawArrays(GL_POINTS, 0, 1);
|
|
}
|
|
|
|
void SketchGrid::paintAxisLabels(QPainter& painter, SketchGrid::SketchPlane plane, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
|
{
|
|
painter.setPen(Qt::white);
|
|
painter.setFont(QFont("Arial", 10));
|
|
|
|
auto params = getGridParams(-m_viewport->camera()->uiCameraDistance());
|
|
const float majorIncrement = params.majorIncrement;
|
|
const int range = params.gridSize;
|
|
|
|
auto drawLabelsForAxis = [&](int axis_idx) {
|
|
int numLabels = range / majorIncrement;
|
|
for (int i = -numLabels; i <= numLabels; ++i) {
|
|
if (i == 0)
|
|
continue;
|
|
|
|
float val = i * majorIncrement;
|
|
QVector3D worldCoord;
|
|
worldCoord[axis_idx] = val;
|
|
|
|
QVector3D screenPos = m_viewport->project(worldCoord, modelView, projection, m_viewport->rect());
|
|
if (screenPos.z() < 1.0f) { // Not clipped
|
|
painter.drawText(screenPos.toPoint(), QString::number(val));
|
|
}
|
|
}
|
|
};
|
|
|
|
if (plane == SketchGrid::XY) {
|
|
drawLabelsForAxis(0); // X
|
|
drawLabelsForAxis(2); // Y
|
|
} else if (plane == SketchGrid::XZ) {
|
|
drawLabelsForAxis(0); // X
|
|
drawLabelsForAxis(1); // Z
|
|
} else if (plane == SketchGrid::YZ) {
|
|
drawLabelsForAxis(1); // Y
|
|
drawLabelsForAxis(2); // Z
|
|
}
|
|
}
|