- 一、预览效果
- 二、关键代码
- 三、代码链接
代码如下:
#include "glwidget.h" #include "drawers/tooldrawer.h" #include三、代码链接#include #include #include #include "../common.h" #define ZOOMSTEP 1.1 GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent), m_shaderProgram(0) { m_animateView = false; m_updatesEnabled = false; m_xRot = 90; m_yRot = 0; m_xRotTarget = 90; m_yRotTarget = 0; m_zoom = 1; m_xPan = 0; m_yPan = 0; m_distance = 100; m_xLookAt = 0; m_yLookAt = 0; m_zLookAt = 0; m_xMin = 0; m_xMax = 0; m_yMin = 0; m_yMax = 0; m_zMin = 0; m_zMax = 0; m_xSize = 0; m_ySize = 0; m_zSize = 0; updateProjection(); updateView(); m_spendTime.setHMS(0, 0, 0); m_estimatedTime.setHMS(0, 0, 0); m_vsync = false; m_targetFps = 60; } GLWidget::~GLWidget() { if (m_shaderProgram) { delete m_shaderProgram; } } double GLWidget::calculateVolume(QVector3D size) { return size.x() * size.y() * size.z(); } void GLWidget::addDrawable(ShaderDrawable *drawable) { m_shaderDrawables.append(drawable); } void GLWidget::fitDrawable(ShaderDrawable *drawable) { stopViewAnimation(); if (drawable != NULL) { updateExtremes(drawable); double a = m_ySize / 2 / 0.25 * 1.3 + (m_zMax - m_zMin) / 2; double b = m_xSize / 2 / 0.25 * 1.3 / ((double)this->width() / this->height()) + (m_zMax - m_zMin) / 2; m_distance = qMax(a, b); if (m_distance == 0) m_distance = 200; m_xLookAt = (m_xMax - m_xMin) / 2 + m_xMin; m_zLookAt = -((m_yMax - m_yMin) / 2 + m_yMin); m_yLookAt = (m_zMax - m_zMin) / 2 + m_zMin; } else { m_distance = 200; m_xLookAt = 0; m_yLookAt = 0; m_zLookAt = 0; m_xMin = 0; m_xMax = 0; m_yMin = 0; m_yMax = 0; m_zMin = 0; m_zMax = 0; m_xSize = 0; m_ySize = 0; m_zSize = 0; } m_xPan = 0; m_yPan = 0; m_zoom = 1; updateProjection(); updateView(); } void GLWidget::updateExtremes(ShaderDrawable *drawable) { if (!qIsNaN(drawable->getMinimumExtremes().x())) m_xMin = drawable->getMinimumExtremes().x(); else m_xMin = 0; if (!qIsNaN(drawable->getMaximumExtremes().x())) m_xMax = drawable->getMaximumExtremes().x(); else m_xMax = 0; if (!qIsNaN(drawable->getMinimumExtremes().y())) m_yMin = drawable->getMinimumExtremes().y(); else m_yMin = 0; if (!qIsNaN(drawable->getMaximumExtremes().y())) m_yMax = drawable->getMaximumExtremes().y(); else m_yMax = 0; if (!qIsNaN(drawable->getMinimumExtremes().z())) m_zMin = drawable->getMinimumExtremes().z(); else m_zMin = 0; if (!qIsNaN(drawable->getMaximumExtremes().z())) m_zMax = drawable->getMaximumExtremes().z(); else m_zMax = 0; m_xSize = m_xMax - m_xMin; m_ySize = m_yMax - m_yMin; m_zSize = m_zMax - m_zMin; } bool GLWidget::antialiasing() const { return m_antialiasing; } void GLWidget::setAntialiasing(bool antialiasing) { m_antialiasing = antialiasing; } void GLWidget::onframesTimer() { m_fps = m_frames; m_frames = 0; QTimer::singleShot(1000, this, SLOT(onframesTimer())); } void GLWidget::viewAnimation() { double t = (double)m_animationframe++ / (m_fps * 0.2); if (t >= 1) stopViewAnimation(); QEasingCurve ec(QEasingCurve::OutExpo); double val = ec.valueForProgress(t); m_xRot = m_xRotStored + double(m_xRotTarget - m_xRotStored) * val; m_yRot = m_yRotStored + double(m_yRotTarget - m_yRotStored) * val; updateView(); } bool GLWidget::vsync() const { return m_vsync; } void GLWidget::setVsync(bool vsync) { m_vsync = vsync; } bool GLWidget::msaa() const { return m_msaa; } void GLWidget::setMsaa(bool msaa) { m_msaa = msaa; } bool GLWidget::updatesEnabled() const { return m_updatesEnabled; } void GLWidget::setUpdatesEnabled(bool updatesEnabled) { m_updatesEnabled = updatesEnabled; } bool GLWidget::zBuffer() const { return m_zBuffer; } void GLWidget::setZBuffer(bool zBuffer) { m_zBuffer = zBuffer; } QString GLWidget::bufferState() const { return m_bufferState; } void GLWidget::setBufferState(const QString &bufferState) { m_bufferState = bufferState; } QString GLWidget::parserStatus() const { return m_parserStatus; } void GLWidget::setParserStatus(const QString &parserStatus) { m_parserStatus = parserStatus; } double GLWidget::lineWidth() const { return m_lineWidth; } void GLWidget::setLineWidth(double lineWidth) { m_lineWidth = lineWidth; } void GLWidget::setTopView() { m_xRotTarget = 90; m_yRotTarget = m_yRot > 180 ? 360 : 0; beginViewAnimation(); } void GLWidget::setFrontView() { m_xRotTarget = 0; m_yRotTarget = m_yRot > 180 ? 360 : 0; beginViewAnimation(); } void GLWidget::setLeftView() { m_xRotTarget = 0; m_yRotTarget = m_yRot > 270 ? 450 : 90; beginViewAnimation(); } int GLWidget::fps() { return m_targetFps; } void GLWidget::setIsometricView() { m_xRotTarget = 45; m_yRotTarget = m_yRot > 180 ? 405 : 45; beginViewAnimation(); } void GLWidget::beginViewAnimation() { m_xRotStored = m_xRot; m_yRotStored = m_yRot; m_animationframe = 0; m_animateView = true; } void GLWidget::stopViewAnimation() { m_animateView = false; } QColor GLWidget::colorText() const { return m_colorText; } void GLWidget::setColorText(const QColor &colorText) { m_colorText = colorText; } QColor GLWidget::colorBackground() const { return m_colorBackground; } void GLWidget::setColorBackground(const QColor &colorBackground) { m_colorBackground = colorBackground; } void GLWidget::setFps(int fps) { if (fps <= 0) return; m_targetFps = fps; m_timerPaint.stop(); m_timerPaint.start(m_vsync ? 30 : 1000 / fps, Qt::PreciseTimer, this); } QTime GLWidget::estimatedTime() const { return m_estimatedTime; } void GLWidget::setEstimatedTime(const QTime &estimatedTime) { m_estimatedTime = estimatedTime; } QTime GLWidget::spendTime() const { return m_spendTime; } void GLWidget::setSpendTime(const QTime &spendTime) { m_spendTime = spendTime; } void GLWidget::initializeGL() { m_shaderProgram = new QOpenGLShaderProgram(); if (m_shaderProgram) { // Compile vertex shader m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl"); // Compile fragment shader m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"); // link shader pipeline m_shaderProgram->link(); qDebug() << "shader program created"; } } void GLWidget::resizeGL(int width, int height) { glViewport(0, 0, width, height); updateProjection(); emit resized(); } void GLWidget::updateProjection() { // Reset projection m_projectionMatrix.setToIdentity(); double asp = (double)width() / height(); m_projectionMatrix.frustum((-0.5 + m_xPan) * asp, (0.5 + m_xPan) * asp, -0.5 + m_yPan, 0.5 + m_yPan, 2, m_distance * 2); } void GLWidget::updateView() { // Set view matrix m_viewMatrix.setToIdentity(); double r = m_distance; double angY = M_PI / 180 * m_yRot; double angX = M_PI / 180 * m_xRot; QVector3D eye(r * cos(angX) * sin(angY) + m_xLookAt, r * sin(angX) + m_yLookAt, r * cos(angX) * cos(angY) + m_zLookAt); QVector3D center(m_xLookAt, m_yLookAt, m_zLookAt); QVector3D up(fabs(m_xRot) == 90 ? -sin(angY + (m_xRot < 0 ? M_PI : 0)) : 0, cos(angX), fabs(m_xRot) == 90 ? -cos(angY + (m_xRot < 0 ? M_PI : 0)) : 0); m_viewMatrix.lookAt(eye, center, up.normalized()); m_viewMatrix.translate(m_xLookAt, m_yLookAt, m_zLookAt); m_viewMatrix.scale(m_zoom, m_zoom, m_zoom); m_viewMatrix.translate(-m_xLookAt, -m_yLookAt, -m_zLookAt); m_viewMatrix.rotate(-90, 1.0, 0.0, 0.0); } void GLWidget::paintEvent(QPaintEvent *pe) { Q_UNUSED(pe) //#endif QPainter painter(this); // Segment counter int vertices = 0; painter.beginNativePainting(); // Clear viewport glClearColor(m_colorBackground.redF(), m_colorBackground.greenF(), m_colorBackground.blueF(), 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Shader drawable points glEnable(GL_PROGRAM_POINT_SIZE); // Update settings if (m_antialiasing) { if (m_msaa) glEnable(GL_MULTISAMPLE); else { glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_LINE_SMOOTH); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glEnable(GL_POINT_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } } if (m_zBuffer) glEnable(GL_DEPTH_TEST); if (m_shaderProgram) { // Draw 3d m_shaderProgram->bind(); // Set modelview-projection matrix m_shaderProgram->setUniformValue("mvp_matrix", m_projectionMatrix * m_viewMatrix); m_shaderProgram->setUniformValue("mv_matrix", m_viewMatrix); // Update geometries in current opengl context foreach (ShaderDrawable *drawable, m_shaderDrawables) if (drawable->needsUpdateGeometry()) drawable->updateGeometry(m_shaderProgram); // Draw geometries foreach (ShaderDrawable *drawable, m_shaderDrawables) { drawable->draw(m_shaderProgram); if (drawable->visible()) vertices += drawable->getVertexCount(); } m_shaderProgram->release(); } // Draw 2D glDisable(GL_DEPTH_TEST); glDisable(GL_MULTISAMPLE); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); painter.endNativePainting(); } void GLWidget::mousePressEvent(QMouseEvent *event) { m_lastPos = event->pos(); m_xLastRot = m_xRot; m_yLastRot = m_yRot; m_xLastPan = m_xPan; m_yLastPan = m_yPan; } void GLWidget::mouseMoveEvent(QMouseEvent *event) { if ((event->buttons() & Qt::MiddleButton && !(event->modifiers() & Qt::ShiftModifier)) || event->buttons() & Qt::LeftButton) { stopViewAnimation(); m_yRot = normalizeAngle(m_yLastRot - (event->pos().x() - m_lastPos.x()) * 0.5); m_xRot = m_xLastRot + (event->pos().y() - m_lastPos.y()) * 0.5; if (m_xRot < -90) m_xRot = -90; if (m_xRot > 90) m_xRot = 90; updateView(); emit rotationChanged(); } if ((event->buttons() & Qt::MiddleButton && event->modifiers() & Qt::ShiftModifier) || event->buttons() & Qt::RightButton) { m_xPan = m_xLastPan - (event->pos().x() - m_lastPos.x()) * 1 / (double)width(); m_yPan = m_yLastPan + (event->pos().y() - m_lastPos.y()) * 1 / (double)height(); updateProjection(); } } void GLWidget::wheelEvent(QWheelEvent *we) { if (m_zoom > 0.1 && we->delta() < 0) { m_xPan -= ((double)we->pos().x() / width() - 0.5 + m_xPan) * (1 - 1 / ZOOMSTEP); m_yPan += ((double)we->pos().y() / height() - 0.5 - m_yPan) * (1 - 1 / ZOOMSTEP); m_zoom /= ZOOMSTEP; } else if (m_zoom < 10 && we->delta() > 0) { m_xPan -= ((double)we->pos().x() / width() - 0.5 + m_xPan) * (1 - ZOOMSTEP); m_yPan += ((double)we->pos().y() / height() - 0.5 - m_yPan) * (1 - ZOOMSTEP); m_zoom *= ZOOMSTEP; } updateProjection(); updateView(); } void GLWidget::timerEvent(QTimerEvent *te) { if (te->timerId() == m_timerPaint.timerId()) { if (m_animateView) viewAnimation(); //#ifndef GLES if (m_updatesEnabled) update(); //#endif } else { //#ifdef GLES QOpenGLWidget::timerEvent(te); //#else // QGLWidget::timerEvent(te); //#endif } } double GLWidget::normalizeAngle(double angle) { while (angle < 0) angle += 360; while (angle > 360) angle -= 360; return angle; }
https://download.csdn.net/download/u013083044/60746173
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)