From f999d87da62e2c5ef41b5f09bb0a4205c50029da Mon Sep 17 00:00:00 2001 From: tangchao0503 <735056338@qq.com> Date: Wed, 24 Dec 2025 16:59:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B02=E8=BD=B4?= =?UTF-8?q?=E7=9A=843D=E6=A8=A1=E5=9E=8B=E8=81=94=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HPPA/HPPA.cpp | 9 +- HPPA/HPPA.h | 4 + HPPA/HPPA.ui | 21 --- HPPA/HPPA.vcxproj | 4 +- HPPA/HPPA.vcxproj.filters | 6 + HPPA/TwoMotorControl.cpp | 2 + HPPA/TwoMotorControl.h | 4 +- HPPA/View3D.cpp | 292 ++++++++++++++++++++++++++++++++++++++ HPPA/View3D.h | 74 ++++++++++ 9 files changed, 391 insertions(+), 25 deletions(-) create mode 100644 HPPA/View3D.cpp create mode 100644 HPPA/View3D.h diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index c61ed0e..bf5ca7c 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -99,7 +99,7 @@ HPPA::HPPA(QWidget* parent) heightScale = 1; //马达位置模拟 - connect(ui.graphicsView->imager, SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onimagerSimulatorMove(int, int))); + //connect(ui.graphicsView->imager, SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onimagerSimulatorMove(int, int))); initPanelToolbar(); setDockNestingEnabled(true); @@ -125,6 +125,10 @@ HPPA::HPPA(QWidget* parent) ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3D模型")); ui.mDockWidgetSpectrometer->setTile(QString::fromLocal8Bit("控制")); + m_view3D_tmp = new View3D("D:\\cpp_project_vs2022\\HPPA\\x64\\Debug\\3DModel\\HPPA_frame.obj", "D:\\cpp_project_vs2022\\HPPA\\x64\\Debug\\3DModel\\HPPA_camera.obj"); + + ui.mDockWidgetSimulator->setWidget(m_view3D_tmp); + //TOC CustomDockWidgetBase* dock_layers = new CustomDockWidgetBase(QString::fromLocal8Bit("layers"), this); dock_layers->setObjectName("mDockLayers"); @@ -574,6 +578,7 @@ void HPPA::initControlTabwidget() tmc = new TwoMotorControl(this); connect(tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int))); connect(tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete())); + connect(tmc, SIGNAL(broadcastLocationSignal(std::vector)), m_view3D_tmp, SLOT(setLoc(std::vector))); tmc->setWindowFlags(Qt::Widget); ui.controlTabWidget->addTab(tmc, QString::fromLocal8Bit("2轴控制")); } @@ -1144,7 +1149,7 @@ void HPPA::setImagerSimulationPos(double x, double y) { x = widthScale * x; y = heightScale * y; - ui.graphicsView->imager->setPos(x, y); + //ui.graphicsView->imager->setPos(x, y); } void HPPA::onimagerSimulatorMove(int x, int y) diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index ebb9fec..920df33 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -46,6 +46,8 @@ #include "CustomDockWidgetBase.h" #include "Carousel.h" +#include "View3D.h" + #define PI 3.1415926 QT_CHARTS_USE_NAMESPACE//QChartView 使用 需要加宏, 否则无法使用 @@ -233,6 +235,8 @@ private: QPushButton* m_open_rgb_camera_btn; QPushButton* m_close_rgb_camera_btn; + View3D* m_view3D_tmp; + public Q_SLOTS: void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber); void PlotSpectral(int state); diff --git a/HPPA/HPPA.ui b/HPPA/HPPA.ui index 436eede..be91a47 100644 --- a/HPPA/HPPA.ui +++ b/HPPA/HPPA.ui @@ -263,22 +263,6 @@ QToolBar QToolButton:hover { 0 - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - @@ -813,11 +797,6 @@ QToolBar QToolButton:hover { QSlider
qdoubleslider.h
- - ImagerPositionSimulation - QGraphicsView -
imagerpositionsimulation.h
-
CustomDockWidgetBase QDockWidget diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index ff8d093..a2fddda 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -32,7 +32,7 @@ 5.13.2_msvc2017_64 - core;network;gui;widgets;serialport;websockets;charts + core;network;gui;widgets;serialport;websockets;3dcore;3danimation;3dextras;3dinput;3dlogic;3drender;3dquick;charts debug @@ -129,6 +129,7 @@ + @@ -163,6 +164,7 @@ + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index d5cad31..00de49a 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -139,6 +139,9 @@ Source Files + + Source Files + @@ -204,6 +207,9 @@ Header Files + + Header Files + diff --git a/HPPA/TwoMotorControl.cpp b/HPPA/TwoMotorControl.cpp index 485cfb3..ff78e4f 100644 --- a/HPPA/TwoMotorControl.cpp +++ b/HPPA/TwoMotorControl.cpp @@ -320,6 +320,8 @@ void TwoMotorControl::displayRealTimeLoc(std::vector loc) tmp = round(loc[1] * 100) / 100; this->ui.ymotor_realTimeLoc_lineEdit->setText(QString::number(tmp)); + + emit broadcastLocationSignal(loc); } void TwoMotorControl::zeroStart() diff --git a/HPPA/TwoMotorControl.h b/HPPA/TwoMotorControl.h index e7cfa56..b1dd553 100644 --- a/HPPA/TwoMotorControl.h +++ b/HPPA/TwoMotorControl.h @@ -26,7 +26,7 @@ public: void record_dark(); void record_white(); - + private: ImagerOperationBase* m_Imager; bool getState(); @@ -84,6 +84,8 @@ signals: void startLineNumSignal(int lineNum); void sequenceComplete();//鎵鏈夐噰闆嗙嚎姝e父杩愯瀹屾垚 + void broadcastLocationSignal(std::vector); + private: Ui::twoMotorControl_UI ui; QThread m_coordinatorThread; diff --git a/HPPA/View3D.cpp b/HPPA/View3D.cpp new file mode 100644 index 0000000..3c920c1 --- /dev/null +++ b/HPPA/View3D.cpp @@ -0,0 +1,292 @@ +锘#include "View3D.h" +#include +#include +#include +#include +#include +#include +#include +#include + +View3D::View3D(const QString& baseModelPath, + const QString& armModelPath, + QWidget* parent) + : QWidget(parent), + m_container(nullptr), + m_baseModelPath(baseModelPath), + m_armModelPath(armModelPath) +{ + m_view = new Qt3DExtras::Qt3DWindow(); + // 閮ㄥ垎 Qt5.9 鏋勫缓鍙兘闇瑕佸己杞 frame graph锛屼絾 defaultFrameGraph() 閫氬父鍙敤 + m_view->defaultFrameGraph()->setClearColor(Qt::white); + + m_rootEntity = new Qt3DCore::QEntity(); + + initScene(); + initCamera(); + + // 鑷姩鏃嬭浆鑷傦紙濡傛灉涓嶉渶瑕佸彲娉ㄩ噴鎺 timer/connect锛 + //connect(&m_timer, &QTimer::timeout, this, [=]() { + // m_angle += 1.0f; + // m_t += 1.0f; + // if (m_angle >= 360.0f) m_angle = 0.0f; + // if (m_armTransform) + // { + // //m_armTransform->setRotationX(m_angle); + // //m_armTransform->setTranslation(QVector3D(m_t, 0, 0)); + // + // Qt3DCore::QTransform transform; + // transform.setTranslation(QVector3D(2, 0, 0)); + + // QMatrix4x4 M = m_armTransform->matrix(); + // M = transform.matrix() * M; // 宸︿箻锛氬湪涓栫晫鍧愭爣绯诲彔鍔 + // m_armTransform->setMatrix(M); + + // qDebug() << m_armTransform->matrix(); + // } + // }); +} + +void View3D::initScene() +{ + // ===== 鍒涘缓 base 鏍硅妭鐐 ===== + auto* baseModel = new Qt3DCore::QEntity(m_rootEntity); + auto* baseLoader = new Qt3DRender::QSceneLoader(baseModel); + baseLoader->setSource(QUrl::fromLocalFile(m_baseModelPath)); + + //connect(baseLoader, &Qt3DRender::QSceneLoader::statusChanged, + // this, &View3D::onSceneLoaderStatusChanged); + + + m_baseTransform = new Qt3DCore::QTransform(); + m_baseTransform->setTranslation(QVector3D(0, 0, 0)); + baseModel->addComponent(baseLoader); + baseModel->addComponent(m_baseTransform); + + // ===== 鍒涘缓 arm 鏍硅妭鐐 ===== + auto* armModel = new Qt3DCore::QEntity(m_rootEntity); + auto* armLoader = new Qt3DRender::QSceneLoader(armModel); + armLoader->setSource(QUrl::fromLocalFile(m_armModelPath)); + + m_armTransform = new Qt3DCore::QTransform(); + m_armTransform->setTranslation(QVector3D(0, 0, 0)); + armModel->addComponent(armLoader); + armModel->addComponent(m_armTransform); + + // 鍧愭爣杞翠緷鐒舵寕鍦 root锛屼笉浼氳绉诲姩 + //createAxes(); + + m_view->setRootEntity(m_rootEntity); + + qDebug() << m_baseTransform->matrix(); + qDebug() << m_armTransform->matrix(); + + //m_armTransform->setTranslation(QVector3D(2000, 0, 0)); + //m_baseTransform->setTranslation(QVector3D(-1000, -1000, -1000)); + + qDebug() << m_baseTransform->matrix(); + qDebug() << m_armTransform->matrix(); +} + +void View3D::createAxes() +{ + // 鍙傛暟 + float axisLength = 500.0f; + float axisRadius = 50.0f; + + // ----- X axis (red) ----- + Qt3DCore::QEntity* xAxis = new Qt3DCore::QEntity(m_rootEntity); + auto* xMesh = new Qt3DExtras::QCylinderMesh(); + xMesh->setRadius(axisRadius); + xMesh->setLength(axisLength); + xMesh->setRings(16); + xMesh->setSlices(16); + + auto* xTrans = new Qt3DCore::QTransform(); + // cylinder 榛樿娌 Y 杞达紝缁 Z 杞 90 搴﹁鍏舵部 X + xTrans->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(0, 0, 1), 90.0f)); + xTrans->setTranslation(QVector3D(axisLength / 2.0f, 0.0f, 0.0f)); + + auto* xMat = new Qt3DExtras::QPhongMaterial(); + xMat->setDiffuse(QColor(Qt::red)); + + xAxis->addComponent(xMesh); + xAxis->addComponent(xTrans); + xAxis->addComponent(xMat); + + // ----- Y axis (green) ----- + Qt3DCore::QEntity* yAxis = new Qt3DCore::QEntity(m_rootEntity); + auto* yMesh = new Qt3DExtras::QCylinderMesh(); + yMesh->setRadius(axisRadius); + yMesh->setLength(axisLength*2); + yMesh->setRings(16); + yMesh->setSlices(16); + + auto* yTrans = new Qt3DCore::QTransform(); + // Y 杞存棤闇鏃嬭浆锛坈ylinder 榛樿娌 Y锛 + yTrans->setTranslation(QVector3D(0.0f, axisLength / 2.0f, 0.0f)); + + auto* yMat = new Qt3DExtras::QPhongMaterial(); + yMat->setDiffuse(QColor(Qt::green)); + + yAxis->addComponent(yMesh); + yAxis->addComponent(yTrans); + yAxis->addComponent(yMat); + + // ----- Z axis (blue) ----- + Qt3DCore::QEntity* zAxis = new Qt3DCore::QEntity(m_rootEntity); + auto* zMesh = new Qt3DExtras::QCylinderMesh(); + zMesh->setRadius(axisRadius); + zMesh->setLength(axisLength*3); + zMesh->setRings(16); + zMesh->setSlices(16); + + auto* zTrans = new Qt3DCore::QTransform(); + // 璁 cylinder 娌 Z锛氱粫 X 杞 90 搴 + zTrans->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 90.0f)); + zTrans->setTranslation(QVector3D(0.0f, 0.0f, axisLength / 2.0f)); + + auto* zMat = new Qt3DExtras::QPhongMaterial(); + zMat->setDiffuse(QColor(Qt::blue)); + + zAxis->addComponent(zMesh); + zAxis->addComponent(zTrans); + zAxis->addComponent(zMat); +} + +void View3D::initCamera() +{ + m_camera = m_view->camera(); + // 16:10 鍋囪绐楀彛姣斾緥锛屽悗缁 resize 鏃剁浉鏈洪忚浼氫繚鎸 + m_camera->lens()->setPerspectiveProjection(50.0f, 16.0f / 10.0f, 0.1f, 10000.0f); + updateCameraPosition(); +} + +void View3D::updateCameraPosition() +{ + float yaw = qDegreesToRadians(m_yawDeg); + float pitch = qDegreesToRadians(m_pitchDeg); + + float x = m_distance * qCos(pitch) * qSin(yaw); + float y = m_distance * qSin(pitch); + float z = m_distance * qCos(pitch) * qCos(yaw); + + QVector3D camPos = m_viewCenter + QVector3D(x, y, z); + m_camera->setPosition(camPos); + m_camera->setViewCenter(m_viewCenter); +} + +void View3D::showEvent(QShowEvent* event) +{ + QWidget::showEvent(event); + + if (!m_container) { + m_container = QWidget::createWindowContainer(m_view, this); + m_view->installEventFilter(this); + + auto* layout = new QHBoxLayout(this); + layout->addWidget(m_container); + layout->setMargin(0); + setLayout(layout); + + // 鍚姩鑷姩鏃嬭浆 timer锛堝鏋滀綘涓嶉渶瑕佸彲浠ユ敞閲婏級 + m_timer.start(100); + } +} + +bool View3D::eventFilter(QObject* obj, QEvent* event) +{ + if (obj == m_view) + { + // 榧犳爣鎸変笅 + if (event->type() == QEvent::MouseButtonPress) { + auto* e = static_cast(event); + if (e->button() == Qt::LeftButton) { + m_mouseDragging = true; + m_lastMousePos = e->pos(); + } + else if (e->button() == Qt::MiddleButton) { + m_middleDragging = true; + m_lastMousePos = e->pos(); + } + } + // 榧犳爣閲婃斁 + else if (event->type() == QEvent::MouseButtonRelease) { + auto* e = static_cast(event); + if (e->button() == Qt::LeftButton) { + m_mouseDragging = false; + } + else if (e->button() == Qt::MiddleButton) { + m_middleDragging = false; + } + } + // 榧犳爣绉诲姩 + else if (event->type() == QEvent::MouseMove) { + auto* e = static_cast(event); + QPoint pos = e->pos(); + QPoint delta = pos - m_lastMousePos; + + // 宸﹂敭锛歰rbit锛堟棆杞級 + if (m_mouseDragging) { + float sensitivity = 0.3f; + m_yawDeg -= delta.x() * sensitivity; + m_pitchDeg += delta.y() * sensitivity; + + if (m_pitchDeg > 89.0f) m_pitchDeg = 89.0f; + if (m_pitchDeg < -89.0f) m_pitchDeg = -89.0f; + + updateCameraPosition(); + } + + // 涓敭锛歱an锛堝钩绉 viewCenter锛 + if (m_middleDragging) { + float speed = 2.0f; + + // 鏍规嵁鎽勫儚鏈烘柟鍚戣绠楀钩绉绘柟鍚 + QVector3D camPos = m_camera->position(); + QVector3D forward = (m_viewCenter - camPos).normalized(); + QVector3D up(0, 1, 0); + QVector3D right = QVector3D::crossProduct(forward, up).normalized(); + + // 涓栫晫鍧愭爣鍙樺寲閲 + QVector3D deltaMove = + -right * (delta.x() * speed) + + up * (delta.y() * speed); + + // 灏嗗钩绉诲簲鐢ㄥ埌涓や釜妯″瀷鏍 Transform + if (m_baseRootTransform) + m_baseRootTransform->setTranslation( + m_baseRootTransform->translation() + deltaMove*-1); + + if (m_armRootTransform) + m_armRootTransform->setTranslation( + m_armRootTransform->translation() + deltaMove*-1); + } + + m_lastMousePos = pos; + } + // 婊氳疆缂╂斁 + else if (event->type() == QEvent::Wheel) { + auto* e = static_cast(event); + // Qt5: angleDelta 杩斿洖鍍忕礌鍊硷紙閫氬父涓 120 per notch锛 + int delta = e->angleDelta().y(); + if (delta == 0) delta = e->delta(); // 澶囬 + m_distance -= delta * 2.0f; // 缂╂斁閫熷害 + if (m_distance < 2.0f) m_distance = 2.0f; + if (m_distance > 10000.0f) m_distance = 10000.0f; + updateCameraPosition(); + } + } + + // 璁 Qt 缁х画澶勭悊锛堜繚鎸佸師琛屼负锛 + return QWidget::eventFilter(obj, event); +} + +void View3D::setLoc(std::vector loc) +{ + double x = round(loc[0] * 100) / 100; + double y = round(loc[1] * 100) / 100; + + + m_armTransform->setTranslation(QVector3D(x, y, 0)); +} diff --git a/HPPA/View3D.h b/HPPA/View3D.h new file mode 100644 index 0000000..20e66ae --- /dev/null +++ b/HPPA/View3D.h @@ -0,0 +1,74 @@ +#ifndef VIEW3D_H +#define VIEW3D_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class View3D : public QWidget +{ + Q_OBJECT +public: + explicit View3D(const QString& baseModelPath, + const QString& armModelPath, + QWidget* parent = nullptr); + +protected: + void showEvent(QShowEvent* event) override; + bool eventFilter(QObject* obj, QEvent* event) override; + +private: + void initScene(); + void initCamera(); + void updateCameraPosition(); + void createAxes(); + +private: + QString m_baseModelPath; + QString m_armModelPath; + + Qt3DExtras::Qt3DWindow* m_view; + QWidget* m_container; + Qt3DCore::QEntity* m_rootEntity; + + Qt3DCore::QEntity* m_baseEntity; + Qt3DCore::QEntity* m_armEntity; + Qt3DCore::QTransform* m_armTransform; + Qt3DCore::QTransform* m_baseTransform; + + QTimer m_timer; + float m_angle = 0; // arm auto rotation + float m_t = 0; + + // ----- Camera control ----- + Qt3DRender::QCamera* m_camera = nullptr; + float m_distance = 5000.0f; + float m_yawDeg = 0.0f; + float m_pitchDeg = 0.0f; + QVector3D m_viewCenter = QVector3D(1000, 1000, -1000); + + // Mouse state + bool m_mouseDragging = false; // left button: orbit + bool m_middleDragging = false; // middle button: pan + QPoint m_lastMousePos; + + Qt3DCore::QTransform* m_baseRootTransform = nullptr; + Qt3DCore::QTransform* m_armRootTransform = nullptr; + +public Q_SLOTS: + void setLoc(std::vector loc); +}; + +#endif // VIEW3D_H