Qt3D C++实现鼠标左键控制摄像机旋转模型,六视图切换,模型自动旋转

相机旋转具体实现如下:

 trackballcameracontroller.h

#ifndef TRACKBALLCAMERACONTROLLER_H
#define TRACKBALLCAMERACONTROLLER_H

#include <Qt3DExtras/QAbstractCameraController>
#include <QPoint>
#include <QSize>
#include <Qt3DCore/QTransform>

class TrackballCameraController : public Qt3DExtras::QAbstractCameraController
{
    Q_OBJECT
public:
    Q_PROPERTY(QSize windowSize READ windowSize WRITE setWindowSize NOTIFY windowSizeChanged)
    Q_PROPERTY(float trackballSize READ trackballSize WRITE setTrackballSize NOTIFY trackballSizeChanged)
    Q_PROPERTY(float rotationSpeed READ rotationSpeed WRITE setRotationSpeed NOTIFY rotationSpeedChanged)

    TrackballCameraController(Qt3DCore::QNode *parent = nullptr);

    QSize windowSize() const
    {
        return m_windowSize;
    }

    float trackballSize() const
    {
        return m_trackballSize;
    }

    float rotationSpeed() const
    {
        return m_rotationSpeed;
    }

public slots:
    void setWindowSize(QSize windowSize)
    {
        if (m_windowSize == windowSize)
            return;

        m_windowSize = windowSize;
        emit windowSizeChanged(m_windowSize);
    }

    void setTrackballSize(float trackballSize)
    {
        if (qFuzzyCompare(m_trackballSize, trackballSize))
            return;

        m_trackballSize = trackballSize;
        emit trackballSizeChanged(m_trackballSize);
    }

    void setRotationSpeed(float rotationSpeed)
    {
        if (qFuzzyCompare(m_rotationSpeed, rotationSpeed))
            return;

        m_rotationSpeed = rotationSpeed;
        emit rotationSpeedChanged(m_rotationSpeed);
    }

signals:
    void windowSizeChanged(QSize windowSize);
    void trackballSizeChanged(float trackballSize);
    void rotationSpeedChanged(float rotationSpeed);

protected:
    void moveCamera(const Qt3DExtras::QAbstractCameraController::InputState &state, float dt) override;
    QVector3D projectToTrackball(const QPoint &screenCoords) const;
    void createRotation(const QPoint &firstPoint,
                               const QPoint &nextPoint, QVector3D &dir, float &angle);

private:
    QPoint m_mouseLastPosition, m_mouseCurrentPosition;
    QSize m_windowSize;
    float m_trackballRadius = 1.0f;
    float m_panSpeed = 1.0f;
    float m_zoomSpeed = 1.0f;
    float m_rotationSpeed = 1.0f;
    float m_zoomCameraLimit = 1.0f;
    float m_trackballSize = 1.0f;
};

#endif // TRACKBALLCAMERACONTROLLER_H

trackballcameracontroller.cpp

#include "trackballcameracontroller.h"
#include <Qt3DRender/QCamera>
#include <QVector2D>
#include <Qt3DInput/QAction>
#include <Qt3DInput/QActionInput>
#include <Qt3DInput/QAxis>
#include <Qt3DInput/QAnalogAxisInput>
#include <Qt3DInput/QMouseDevice>
#include <Qt3DInput/QKeyboardDevice>
#include <Qt3DInput/QMouseHandler>
#include <Qt3DInput/QKeyboardHandler>
#include <Qt3DCore/QTransform>
#include <QtMath>

TrackballCameraController::TrackballCameraController(Qt3DCore::QNode *parent)
    : Qt3DExtras::QAbstractCameraController (parent)
{
    Qt3DInput::QMouseHandler *mouseHandler = new Qt3DInput::QMouseHandler(this);
    mouseHandler->setSourceDevice(mouseDevice());

    QObject::connect(mouseHandler, &Qt3DInput::QMouseHandler::pressed,
                     [this](Qt3DInput::QMouseEvent *pressedEvent) {
        pressedEvent->setAccepted(true);
        m_mouseLastPosition = QPoint(pressedEvent->x(), pressedEvent->y());
        m_mouseCurrentPosition = m_mouseLastPosition;
    });

    QObject::connect(mouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
                     [this](Qt3DInput::QMouseEvent *positionChangedEvent) {
        positionChangedEvent->setAccepted(true);
        m_mouseCurrentPosition = QPoint(positionChangedEvent->x(),
                                              positionChangedEvent->y());
    });
    //keyboardDevice()->set
}

QVector3D TrackballCameraController::projectToTrackball(const QPoint &screenCoords) const
{
    float sx = screenCoords.x(), sy = m_windowSize.height() - screenCoords.y();

    QVector2D p2d(sx / m_windowSize.width() - 0.5f, sy / m_windowSize.height() - 0.5f);
    //qDebug()<<p2d;

    float z = 0.0f;
    float r2 = m_trackballSize * m_trackballSize;
    if (p2d.lengthSquared() <= r2 * 0.5f){
        z = sqrt(r2 - p2d.lengthSquared());
    }else{
        z = r2 * 0.5f / p2d.length();
    }
    QVector3D p3d(p2d, z);
    //qDebug()<<p3d;
    return p3d;
}

float clamp(float x)
{
    return x > 1? 1 : (x < -1? -1 : x);
}

void TrackballCameraController::createRotation(const QPoint &firstPoint, const QPoint &nextPoint,
                                               QVector3D &dir, float &angle)
{
    auto lastPos3D = projectToTrackball(firstPoint).normalized();
    auto currentPos3D = projectToTrackball(nextPoint).normalized();

    // Compute axis of rotation:
    dir = QVector3D::crossProduct(currentPos3D, lastPos3D);

    // Approximate rotation angle:
    //qDebug()<<"dot:"<<QVector3D::dotProduct(currentPos3D, lastPos3D);
    angle = acos(clamp(QVector3D::dotProduct(currentPos3D, lastPos3D)));

    //qDebug()<<"dir:"<<dir<<"angle:"<<angle;
}

void TrackballCameraController::moveCamera(const Qt3DExtras::QAbstractCameraController::InputState &state, float dt)
{
    auto theCamera = camera();

    if(theCamera == nullptr)
        return;

    auto ls = linearSpeed();


    if(state.leftMouseButtonActive){
        QVector3D dir;
        float angle;
        createRotation(m_mouseLastPosition, m_mouseCurrentPosition, dir, angle);

        auto currentRotation = theCamera->transform()->rotation();

        auto rotatedAxis = currentRotation.rotatedVector(dir);
        angle *= m_rotationSpeed;

        theCamera->rotateAboutViewCenter(QQuaternion::fromAxisAndAngle(rotatedAxis, angle * M_1_PI * 180));
    }else if(state.middleMouseButtonActive){
        auto offset = m_mouseCurrentPosition - m_mouseLastPosition;
        qDebug()<<"offset:"<<offset;
        theCamera->translate(QVector3D(-offset.x() / float(m_windowSize.width()) * ls,
                                      offset.y() / float(m_windowSize.height()) * ls,
                                      0));


    }else if(dt != 0){
        qDebug()<<"dt:"<<dt;
        theCamera->translate(QVector3D(state.txAxisValue * ls,
                                      state.tyAxisValue * ls,
                                      state.tzAxisValue * ls) * dt,
                             Qt3DRender::QCamera::DontTranslateViewCenter);
    }
    m_mouseLastPosition = m_mouseCurrentPosition;
}

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Qt实现鼠标移动控制模型旋转的代码,可以使用QQuaternion和QVector3D类来实现。具体步骤如下: 1. 在Qt中创建一个OpenGL窗口,用于绘制模型。 2. 在窗口类中重写鼠标事件函数,实现鼠标移动时模型旋转。 3. 在鼠标移动事件中,根据鼠标移动的距离计算旋转的角度。 4. 使用QQuaternion类创建一个四元数,表示旋转的角度和旋转轴。 5. 使用QVector3D类创建一个向量,表示旋转轴的方向。 6. 将四元数和向量应用到模型矩阵中,实现模型旋转。 下面是一个示例代码,用于实现鼠标移动控制模型旋转: ```c++ void MyGLWidget::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { // 鼠标按下时,计算旋转角度 QPoint pos = event->pos() - lastPos; float dx = pos.x() / float(width()); float dy = pos.y() / float(height()); float angle = sqrt(dx*dx + dy*dy) * 180 / M_PI; // 计算旋转轴 QVector3D axis = QVector3D(dy, dx, 0.0).normalized(); // 创建四元数 QQuaternion rot = QQuaternion::fromAxisAndAngle(axis, angle); // 应用旋转变换到模型矩阵中 modelMatrix.rotate(rot); // 重新绘制场景 update(); // 记录上一次鼠标位置 lastPos = event->pos(); } } void MyGLWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { // 记录鼠标按下时的位置 lastPos = event->pos(); } } ``` 上述代码中,modelMatrix表示模型的变换矩阵,可以使用QMatrix4x4类来创建和操作。在mouseMoveEvent函数中,首先计算鼠标移动的距离,然后根据距离计算旋转角度和旋转轴。接着使用QQuaternion类创建一个四元数,表示旋转变换,使用rotate函数将变换应用到模型矩阵中。最后调用update函数重新绘制场景即可。在mousePressEvent函数中,记录鼠标按下时的位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值