最近关于点云的处理,需要搭建一个可视化的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"个点");
}