c++ - 使用 Qt 和 OpenGL 的弧球控件

标签 c++ qt opengl arcball

我正在尝试使用 Open GL 和 Qt 实现弧球/轨迹球 Controller 。但是,我对 OpenGL 很陌生。我正在经历一段糟糕、糟糕、糟糕的时间让一切正常运转。

我开始关注这个视频:https://www.youtube.com/watch?v=3IQV65ApWGs

我正在为我的窗口使用 Qt,使用他们的 QtWidget 类。

基本上,我在原点周围有一个立方体。我想用鼠标围绕立方体旋转相机。现在,当我拖动时,立方体围绕球体运行时,相机似乎保持不动。有点与我需要的相反。

希望大家帮帮忙。我觉得我几乎尝试了这里的一切。

首先我的鼠标处理:

void GLWidget::wheelEvent(QWheelEvent *e){
    scrollDelta +=  e->delta() / 120;
}

void GLWidget::mousePressEvent(QMouseEvent *e){
    rotate=false;
    if(e->button() == Qt::LeftButton){
        oldX = e->x(); // Set this to the mouse position
        oldY = e->y(); // Set this to the mouse position

        newX = e->x();
        newY = e->y();

        qDebug() << oldX << oldY << newX << newY;

        rotate = true;

        useArcBall = true;
     }
}

void GLWidget::mouseMoveEvent(QMouseEvent *e){
    if(e->buttons() & Qt::LeftButton){
        //qDebug() << QString::number(e->x());
        if(rotate){
            newX = e->x();
            newY = e->y();
            updateMouse();

        }
        oldX = e->x();
        oldY = e->y();
    }

}

void GLWidget::mouseReleaseEvent(QMouseEvent *e){
    if(e->button() == Qt::LeftButton)
        useArcBall = false;

}

void GLWidget::updateMouse()
{

        QVector3D v = getArcBallVector(oldX,oldY); // from the mouse
        QVector3D u = getArcBallVector(newX, newY);

        float angle = std::acos(std::min(1.0f, QVector3D::dotProduct(u,v)));

        QVector3D rotAxis = QVector3D::crossProduct(v,u);

        QMatrix4x4 eye2ObjSpaceMat = rotationMat.inverted();

        QVector3D objSpaceRotAxis = eye2ObjSpaceMat * rotAxis;

        qDebug() << 4 * qRadiansToDegrees(angle);


        //modelview.rotate(4 * qRadiansToDegrees(angle), rotAxis);

        //oldRot = newRot;

        //oldX = newX;
        //oldY = newY;

        //qDebug() << objSpaceRotAxis.normalized();


    if(true){
    rotationMat.rotate(4 * qRadiansToDegrees(angle), objSpaceRotAxis);
    }

}

现在是弧球相关的数学:

QVector3D GLWidget::getArcBallVector(int x, int y)
{
   QVector3D pt = QVector3D(2.0 * x / GLWidget::width() - 1.0, 2.0 * y / GLWidget::height() - 1.0 , 0);
   pt.setY(pt.y() * -1);

   // compute z-coordinates

   float xySquared = pt.x() * pt.x() + pt.y() * pt.y();

   if(xySquared <= 1.0)

       pt.setZ(std::sqrt(1.0 - xySquared));
   else
       pt.normalize();

   return pt;

}

这是我渲染所有内容的部分:

void GLWidget::paintGL() { QMatrix4x4 模型 View ;

QPainter painter;
painter.begin(this);

painter.beginNativePainting();

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glFrontFace(GL_CW);
glCullFace(GL_FRONT);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);


 modelview.perspective(90.0f, 4.0f / 3.0f, 0.1f, 3000.0f);

modelview.lookAt(QVector3D(eyeX,eyeY,eyeZ), QVector3D(0,0,0), QVector3D(0,1,0));


// New Trackball code

modelview = rotationMat * modelview;

modelview.scale(1 - scrollDelta / 10);

我做错了什么? 我的方法不合理吗?

更新 所以我修复了一些鼠标处理。现在我的问题是立方体围绕球体表面旋转,而不是相机。这是因为我正在使用 lookat 命令吗?

另外,当我转动立方体时,立方体被背景色遮挡了。这是投影问题吗?

最佳答案

看起来你的矩阵应用顺序错误

paintGL 中你应该这样做:

modelview *= rotationMat;

在 updateMouse 中你应该做

QMatrix4x4 tmp;
tmp.rotate(4 * qRadiansToDegrees(angle), objSpaceRotAxis);
rotationMat = tmp * rotationMat;

关于c++ - 使用 Qt 和 OpenGL 的弧球控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23747013/

相关文章:

c++ - 直通几何着色器

c++ - SSBO 哈希表,缺失值

c++ - 返回不同类型变量的单个 get 方法

c++ - 使用 std::sort 计算交换

qt - 如何发送包含 cv::Mat 的 Qt 信号?

c++ - Qt -"\n"不起作用,但 std::endl 可以吗?

C++ libusb : how to send data to device?

opengl - 片段着色器 GLSL 中的颜色插值?

java - 用于从 xsd 生成 C++ 类的 JAXB 等价物?

c++ - 在圆圈周围放置一个 ofImage