今天开始学编程 2024-12-24 15:50 采纳率: 0%
浏览 30

Qt 3D的视图移动怎么做到?

最近关于点云的处理,需要搭建一个可视化的UI。但是用Qt3D搭建好之后,能显示但是不能控制视图的移动,请各位帮忙看看为什么无法控制视图旋转平移。日志是有正常输出的,没有其他报错,也能正常更新点云。
窗口的构造函数:


RPScanRec::RPScanRec(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    this->showMaximized();

    m_sceneRoot = new Qt3DCore::QEntity;
    m_view = new Qt3DExtras::Qt3DWindow;

    // 将3D视图添加到布局中
    m_container = QWidget::createWindowContainer(m_view);
    m_container->setFocusPolicy(Qt::StrongFocus); // 设置焦点策略
    ui.horizontalLayout_2->addWidget(m_container);
    //m_view->showMaximized();
    //m_view->show();
    setupScene();

    connect(this, &RPScanRec::sigUpdateImage, this, &RPScanRec::OnSigUpdateImage);

    connect(&m_socket, &QTcpSocket::connected, this, &RPScanRec::onConnected);
    connect(&m_socket, &QTcpSocket::disconnected, this, &RPScanRec::onDisconnected);
    connect(&m_socket, &QTcpSocket::readyRead, this, &RPScanRec::onReadyRead);

    connect(this, SIGNAL(sigLogOut(QString)), this, SLOT(OnSigLogOut(QString)));

    connect(&m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::errorOccurred),
        this, &RPScanRec::onError);

    m_socket.connectToHost(m_IP, m_Port);
}

setupScene():

void RPScanRec::setupScene()
{
    // 设置相机
    m_camera = m_view->camera();

    // 设置透视投影参数,扩大远裁剪面以覆盖 Z = -1050 的点
    m_camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 20000.0f);

    // 将相机放置在一个更合适的 Z 位置,确保能看到从 -1050 到 800 的 Z 值范围
    m_camera->setPosition(QVector3D(0, 0, 10000));
    m_camera->setViewCenter(QVector3D(0, 0, 0));

    // 添加相机控制器
    m_camController = new Qt3DExtras::QOrbitCameraController(m_sceneRoot);
    if (m_camController)
    {
        m_camController->setLinearSpeed(5000.0f);
        m_camController->setLookSpeed(180.0f);
        m_camController->setCamera(m_camera);
    }

    // 将场景根节点设置为视图的根实体
    m_view->setRootEntity(m_sceneRoot);

    // 打印调试信息
    qDebug() << "Setup scene with adjusted camera settings and camera controller set up with camera" << m_camera;
}


 loadPointCloud():

void RPScanRec::loadPointCloud(const QString& filePath)
{
    // 清除现有点云数据(如果有的话)
    qDeleteAll(m_sceneRoot->children()); // 使用qDeleteAll简化删除过程

    QVector<QVector3D> points;

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "Failed to open file:" << filePath << ". Error:" << file.errorString();
        emit sigLogOut(u8"打开文件失败:" + filePath + ". Error:" + file.errorString());
        return;
    }

    QTextStream in(&file);
    float m_zMin = std::numeric_limits<float>::max();
    float m_zMax = std::numeric_limits<float>::lowest();

    // 第一遍遍历:找到最小和最大的Z值用于颜色映射
    while (!in.atEnd()) {
        QString line = in.readLine();
        QStringList values = line.split(' ', Qt::SkipEmptyParts);
        if (values.size() == 3) {
            bool okX, okY, okZ;
            float x = values[0].toFloat(&okX);
            float y = values[1].toFloat(&okY);
            float z = values[2].toFloat(&okZ);
            if (okX && okY && okZ) {
                points.append(QVector3D(x, y, z));
                m_zMin = std::min(m_zMin, z);
                m_zMax = std::max(m_zMax, z);
            }
        }
    }
    file.close();

    if (points.isEmpty()) {
        qWarning() << "No valid points found in the file.";
        emit sigLogOut(u8"文件没有有效点");
        return;
    }

    // 创建几何体
    m_geometry = new Qt3DRender::QGeometry(m_sceneRoot);

    // 创建位置属性
    QByteArray vertexBufferData;
    for (const auto& point : points) {
        vertexBufferData.append(reinterpret_cast<const char*>(&point), sizeof(float) * 3);
    }
    Qt3DRender::QBuffer* vertexBuffer = new Qt3DRender::QBuffer(m_geometry);
    vertexBuffer->setData(vertexBufferData);

    Qt3DRender::QAttribute* positionAttribute = new Qt3DRender::QAttribute(m_geometry);
    positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
    positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
    positionAttribute->setVertexSize(3);
    positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
    positionAttribute->setByteStride(sizeof(float) * 3);
    positionAttribute->setCount(points.size());
    positionAttribute->setBuffer(vertexBuffer);
    m_geometry->addAttribute(positionAttribute);

    // 创建几何体渲染器
    m_geometryRenderer = new Qt3DRender::QGeometryRenderer(m_sceneRoot);
    m_geometryRenderer->setGeometry(m_geometry);
    m_geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Points);

    // 设置材质并固定点大小
    m_material = new Qt3DExtras::QPhongMaterial(m_sceneRoot);
    m_material->setDiffuse(Qt::red);

    // 设置较大的点大小以便于调试
    Qt3DRender::QParameter* pointSizeParam = new Qt3DRender::QParameter("pointSize", QVariant(1.0f));
    m_material->addParameter(pointSizeParam);

    // 创建实体
    Qt3DCore::QEntity* pointCloudEntity = new Qt3DCore::QEntity(m_sceneRoot);
    pointCloudEntity->addComponent(m_geometryRenderer);
    pointCloudEntity->addComponent(m_material);

    qDebug() << "Loaded" << points.size() << "points into the scene.";
    emit sigLogOut(u8"加载了" + QString::number(points.size()) + u8"个点");
}


  • 写回答

1条回答 默认 最新

  • 关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    在Qt 3D中,视图移动通常是通过摄像机(Camera)来实现的。你已经设置了摄像机(m_camera)和摄像机控制器(m_camController),这样用户就应该可以通过鼠标和键盘来操作视图了。摄像机控制器负责处理用户的输入,并更新摄像机的位置和朝向等属性,从而实现视图的移动。

    根据你提供的代码,看起来你的视图设置是正确的。如果你无法控制视图移动,可能的原因包括:

    1. 确保摄像机控制器已经正确添加到场景中。你在setupScene()函数中创建了一个摄像机控制器并添加到了m_sceneRoot,这看起来是正确的。但是你需要确保m_sceneRoot实际上是场景的正确根实体。
    2. 确保摄像机控制器与摄像机正确关联。你在创建摄像机控制器时将其与摄像机关联,这看起来也是正确的。
    3. 检查是否有其他代码干扰了视图。比如,可能有其他代码修改了摄像机的位置或朝向,或者禁用了摄像机控制器。
    4. 确保你的应用程序聚焦在Qt3DWindow上。如果窗口没有焦点,用户输入可能不会被摄像机控制器接收。

    如果你确认以上都正确,但仍然无法移动视图,你可以尝试以下操作来进一步调试:

    • setupScene()函数中,检查m_camController是否成功创建并正确关联了摄像机。可以在创建m_camController后立即检查其状态。
    • 确保你的应用程序在调用setupScene()之后没有其他代码修改了摄像机的设置。
    • 尝试在不同的设备或操作系统上测试你的应用程序,看看问题是否仍然存在。

    如果问题仍然存在,你可能需要查看Qt的日志输出或调试信息来进一步诊断问题。你也可以尝试简化你的代码,只保留与视图移动相关的部分,然后逐步添加其他代码,以便找到问题的根源。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月24日