Реструктуризация проекта и генератор синтетических датасетов эхолота.
Перенесены backend/frontend/desktop/engine, добавлены вкладки конструктора сцен и генератора датасета с параметрами лучей и длины сетки рельефа, обновлены API и Docker-сборка. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
#include "glview.h"
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QMouseEvent>
|
||||
#include <QVector3D>
|
||||
#include <QWheelEvent>
|
||||
#include <QtMath>
|
||||
|
||||
GlView::GlView(QWidget *parent)
|
||||
: QOpenGLWidget(parent)
|
||||
, m_yawDeg(-30.0f)
|
||||
, m_pitchDeg(25.0f)
|
||||
, m_distance(4.0f)
|
||||
, m_minDistance(0.5f)
|
||||
, m_maxDistance(2000.0f)
|
||||
, m_center(0.0f, 0.0f, 0.0f)
|
||||
, m_radius(1.0f)
|
||||
, m_panX(0.0f)
|
||||
, m_panY(0.0f)
|
||||
, m_surfaceVisible(true)
|
||||
{
|
||||
}
|
||||
|
||||
void GlView::setData(const QVector<core::Point3f> &points, const QVector<core::Triangle> &triangles)
|
||||
{
|
||||
m_points = points;
|
||||
m_triangles = triangles;
|
||||
|
||||
if (!m_points.isEmpty()) {
|
||||
QVector3D bmin(m_points[0].x, m_points[0].y, m_points[0].z);
|
||||
QVector3D bmax = bmin;
|
||||
for (const core::Point3f &p : m_points) {
|
||||
bmin.setX(qMin(bmin.x(), p.x));
|
||||
bmin.setY(qMin(bmin.y(), p.y));
|
||||
bmin.setZ(qMin(bmin.z(), p.z));
|
||||
bmax.setX(qMax(bmax.x(), p.x));
|
||||
bmax.setY(qMax(bmax.y(), p.y));
|
||||
bmax.setZ(qMax(bmax.z(), p.z));
|
||||
}
|
||||
|
||||
m_center = (bmin + bmax) * 0.5f;
|
||||
m_radius = qMax(1e-3f, (bmax - bmin).length() * 0.5f);
|
||||
m_distance = qMax(2.5f * m_radius, 1.0f);
|
||||
m_minDistance = qMax(0.05f * m_radius, 0.01f);
|
||||
m_maxDistance = qMax(100.0f * m_radius, m_distance * 2.0f);
|
||||
m_panX = 0.0f;
|
||||
m_panY = 0.0f;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void GlView::setSurfaceVisible(const bool visible)
|
||||
{
|
||||
if (m_surfaceVisible == visible) {
|
||||
return;
|
||||
}
|
||||
m_surfaceVisible = visible;
|
||||
update();
|
||||
}
|
||||
|
||||
void GlView::initializeGL()
|
||||
{
|
||||
initializeOpenGLFunctions();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
|
||||
"attribute vec3 aPos;\n"
|
||||
"uniform mat4 uMvp;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = uMvp * vec4(aPos, 1.0);\n"
|
||||
"}\n");
|
||||
m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
|
||||
"uniform vec3 uColor;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = vec4(uColor, 1.0);\n"
|
||||
"}\n");
|
||||
m_program.link();
|
||||
}
|
||||
|
||||
void GlView::resizeGL(int w, int h)
|
||||
{
|
||||
glViewport(0, 0, w, h);
|
||||
}
|
||||
|
||||
void GlView::paintGL()
|
||||
{
|
||||
glClearColor(0.08f, 0.09f, 0.11f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
if (m_points.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<float> vertices;
|
||||
vertices.reserve(m_points.size() * 3);
|
||||
for (const core::Point3f &p : m_points) {
|
||||
vertices.push_back(p.x - m_center.x());
|
||||
vertices.push_back(p.y - m_center.y());
|
||||
vertices.push_back(p.z - m_center.z());
|
||||
}
|
||||
|
||||
QVector<GLuint> indices;
|
||||
indices.reserve(m_triangles.size() * 3);
|
||||
QVector<GLuint> edgeIndices;
|
||||
edgeIndices.reserve(m_triangles.size() * 6);
|
||||
for (const core::Triangle &t : m_triangles) {
|
||||
indices.push_back(static_cast<GLuint>(t.i0));
|
||||
indices.push_back(static_cast<GLuint>(t.i1));
|
||||
indices.push_back(static_cast<GLuint>(t.i2));
|
||||
|
||||
edgeIndices.push_back(static_cast<GLuint>(t.i0));
|
||||
edgeIndices.push_back(static_cast<GLuint>(t.i1));
|
||||
edgeIndices.push_back(static_cast<GLuint>(t.i1));
|
||||
edgeIndices.push_back(static_cast<GLuint>(t.i2));
|
||||
edgeIndices.push_back(static_cast<GLuint>(t.i2));
|
||||
edgeIndices.push_back(static_cast<GLuint>(t.i0));
|
||||
}
|
||||
|
||||
QMatrix4x4 projection;
|
||||
projection.perspective(45.0f,
|
||||
static_cast<float>(width()) / qMax(1, height()),
|
||||
qMax(0.001f, m_distance * 0.001f),
|
||||
qMax(m_distance + 4.0f * m_radius, m_distance * 2.0f));
|
||||
|
||||
QMatrix4x4 view;
|
||||
view.translate(m_panX, m_panY, -m_distance);
|
||||
view.rotate(m_pitchDeg, 1.0f, 0.0f, 0.0f);
|
||||
view.rotate(m_yawDeg, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
const QMatrix4x4 mvp = projection * view;
|
||||
|
||||
m_program.bind();
|
||||
m_program.setUniformValue("uMvp", mvp);
|
||||
m_program.enableAttributeArray("aPos");
|
||||
m_program.setAttributeArray("aPos", GL_FLOAT, vertices.constData(), 3);
|
||||
|
||||
if (m_surfaceVisible) {
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(1.0f, 1.0f);
|
||||
m_program.setUniformValue("uColor", QVector3D(0.20f, 0.72f, 0.95f));
|
||||
if (!indices.isEmpty()) {
|
||||
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, indices.constData());
|
||||
}
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
glLineWidth(2.2f);
|
||||
m_program.setUniformValue("uColor", QVector3D(1.0f, 0.2f, 0.08f));
|
||||
if (!edgeIndices.isEmpty()) {
|
||||
glDrawElements(GL_LINES, edgeIndices.size(), GL_UNSIGNED_INT, edgeIndices.constData());
|
||||
}
|
||||
}
|
||||
|
||||
glPointSize(4.0f);
|
||||
m_program.setUniformValue("uColor", QVector3D(1.0f, 0.85f, 0.2f));
|
||||
glDrawArrays(GL_POINTS, 0, m_points.size());
|
||||
|
||||
m_program.disableAttributeArray("aPos");
|
||||
m_program.release();
|
||||
}
|
||||
|
||||
void GlView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
m_lastMousePos = event->pos();
|
||||
}
|
||||
|
||||
void GlView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
const QPoint delta = event->pos() - m_lastMousePos;
|
||||
m_lastMousePos = event->pos();
|
||||
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
m_yawDeg += static_cast<float>(delta.x()) * 0.5f;
|
||||
m_pitchDeg += static_cast<float>(delta.y()) * 0.5f;
|
||||
m_pitchDeg = qBound(-89.0f, m_pitchDeg, 89.0f);
|
||||
update();
|
||||
} else if (event->buttons() & (Qt::RightButton | Qt::MiddleButton)) {
|
||||
const float panScale = qMax(0.0005f * m_distance, 0.0005f);
|
||||
m_panX += static_cast<float>(delta.x()) * panScale;
|
||||
m_panY -= static_cast<float>(delta.y()) * panScale;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void GlView::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
const float step = static_cast<float>(event->angleDelta().y()) / 120.0f;
|
||||
const float zoomFactor = qPow(1.15f, step);
|
||||
m_distance /= zoomFactor;
|
||||
m_distance = qBound(m_minDistance, m_distance, m_maxDistance);
|
||||
update();
|
||||
}
|
||||
Reference in New Issue
Block a user