初步实现2轴的3D模型联动
This commit is contained in:
@ -99,7 +99,7 @@ HPPA::HPPA(QWidget* parent)
|
|||||||
heightScale = 1;
|
heightScale = 1;
|
||||||
|
|
||||||
//<2F><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>ģ<EFBFBD><C4A3>
|
//<2F><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>ģ<EFBFBD><C4A3>
|
||||||
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();
|
initPanelToolbar();
|
||||||
setDockNestingEnabled(true);
|
setDockNestingEnabled(true);
|
||||||
@ -125,6 +125,10 @@ HPPA::HPPA(QWidget* parent)
|
|||||||
ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3Dģ<EFBFBD><EFBFBD>"));
|
ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3Dģ<EFBFBD><EFBFBD>"));
|
||||||
ui.mDockWidgetSpectrometer->setTile(QString::fromLocal8Bit("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
|
ui.mDockWidgetSpectrometer->setTile(QString::fromLocal8Bit("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
|
||||||
|
|
||||||
|
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
|
//TOC
|
||||||
CustomDockWidgetBase* dock_layers = new CustomDockWidgetBase(QString::fromLocal8Bit("layers"), this);
|
CustomDockWidgetBase* dock_layers = new CustomDockWidgetBase(QString::fromLocal8Bit("layers"), this);
|
||||||
dock_layers->setObjectName("mDockLayers");
|
dock_layers->setObjectName("mDockLayers");
|
||||||
@ -574,6 +578,7 @@ void HPPA::initControlTabwidget()
|
|||||||
tmc = new TwoMotorControl(this);
|
tmc = new TwoMotorControl(this);
|
||||||
connect(tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int)));
|
connect(tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int)));
|
||||||
connect(tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete()));
|
connect(tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete()));
|
||||||
|
connect(tmc, SIGNAL(broadcastLocationSignal(std::vector<double>)), m_view3D_tmp, SLOT(setLoc(std::vector<double>)));
|
||||||
tmc->setWindowFlags(Qt::Widget);
|
tmc->setWindowFlags(Qt::Widget);
|
||||||
ui.controlTabWidget->addTab(tmc, QString::fromLocal8Bit("2<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
|
ui.controlTabWidget->addTab(tmc, QString::fromLocal8Bit("2<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
|
||||||
}
|
}
|
||||||
@ -1144,7 +1149,7 @@ void HPPA::setImagerSimulationPos(double x, double y)
|
|||||||
{
|
{
|
||||||
x = widthScale * x;
|
x = widthScale * x;
|
||||||
y = heightScale * y;
|
y = heightScale * y;
|
||||||
ui.graphicsView->imager->setPos(x, y);
|
//ui.graphicsView->imager->setPos(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HPPA::onimagerSimulatorMove(int x, int y)
|
void HPPA::onimagerSimulatorMove(int x, int y)
|
||||||
|
|||||||
@ -46,6 +46,8 @@
|
|||||||
#include "CustomDockWidgetBase.h"
|
#include "CustomDockWidgetBase.h"
|
||||||
#include "Carousel.h"
|
#include "Carousel.h"
|
||||||
|
|
||||||
|
#include "View3D.h"
|
||||||
|
|
||||||
#define PI 3.1415926
|
#define PI 3.1415926
|
||||||
|
|
||||||
QT_CHARTS_USE_NAMESPACE//QChartView ʹ<><CAB9> <20><>Ҫ<EFBFBD>Ӻ꣬ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>
|
QT_CHARTS_USE_NAMESPACE//QChartView ʹ<><CAB9> <20><>Ҫ<EFBFBD>Ӻ꣬ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>
|
||||||
@ -233,6 +235,8 @@ private:
|
|||||||
QPushButton* m_open_rgb_camera_btn;
|
QPushButton* m_open_rgb_camera_btn;
|
||||||
QPushButton* m_close_rgb_camera_btn;
|
QPushButton* m_close_rgb_camera_btn;
|
||||||
|
|
||||||
|
View3D* m_view3D_tmp;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber);
|
void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber);
|
||||||
void PlotSpectral(int state);
|
void PlotSpectral(int state);
|
||||||
|
|||||||
21
HPPA/HPPA.ui
21
HPPA/HPPA.ui
@ -263,22 +263,6 @@ QToolBar QToolButton:hover {
|
|||||||
<property name="verticalSpacing">
|
<property name="verticalSpacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="ImagerPositionSimulation" name="graphicsView">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::NoFrame</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Raised</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
@ -813,11 +797,6 @@ QToolBar QToolButton:hover {
|
|||||||
<extends>QSlider</extends>
|
<extends>QSlider</extends>
|
||||||
<header>qdoubleslider.h</header>
|
<header>qdoubleslider.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>ImagerPositionSimulation</class>
|
|
||||||
<extends>QGraphicsView</extends>
|
|
||||||
<header>imagerpositionsimulation.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>CustomDockWidgetBase</class>
|
<class>CustomDockWidgetBase</class>
|
||||||
<extends>QDockWidget</extends>
|
<extends>QDockWidget</extends>
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||||
<QtInstall>5.13.2_msvc2017_64</QtInstall>
|
<QtInstall>5.13.2_msvc2017_64</QtInstall>
|
||||||
<QtModules>core;network;gui;widgets;serialport;websockets;charts</QtModules>
|
<QtModules>core;network;gui;widgets;serialport;websockets;3dcore;3danimation;3dextras;3dinput;3dlogic;3drender;3dquick;charts</QtModules>
|
||||||
<QtBuildConfig>debug</QtBuildConfig>
|
<QtBuildConfig>debug</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
||||||
@ -129,6 +129,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="TwoMotorControl.cpp" />
|
<ClCompile Include="TwoMotorControl.cpp" />
|
||||||
<ClCompile Include="utility_tc.cpp" />
|
<ClCompile Include="utility_tc.cpp" />
|
||||||
|
<ClCompile Include="View3D.cpp" />
|
||||||
<QtRcc Include="HPPA.qrc" />
|
<QtRcc Include="HPPA.qrc" />
|
||||||
<QtUic Include="about.ui" />
|
<QtUic Include="about.ui" />
|
||||||
<QtUic Include="adjustTable.ui" />
|
<QtUic Include="adjustTable.ui" />
|
||||||
@ -163,6 +164,7 @@
|
|||||||
<QtMoc Include="image2display.h" />
|
<QtMoc Include="image2display.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<QtMoc Include="View3D.h" />
|
||||||
<QtMoc Include="adjustTable.h" />
|
<QtMoc Include="adjustTable.h" />
|
||||||
<QtMoc Include="PowerControl.h" />
|
<QtMoc Include="PowerControl.h" />
|
||||||
<QtMoc Include="RobotArmControl.h" />
|
<QtMoc Include="RobotArmControl.h" />
|
||||||
|
|||||||
@ -139,6 +139,9 @@
|
|||||||
<ClCompile Include="Carousel.cpp">
|
<ClCompile Include="Carousel.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="View3D.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="fileOperation.h">
|
<QtMoc Include="fileOperation.h">
|
||||||
@ -204,6 +207,9 @@
|
|||||||
<QtMoc Include="Carousel.h">
|
<QtMoc Include="Carousel.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
|
<QtMoc Include="View3D.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</QtMoc>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="imageProcessor.h">
|
<ClInclude Include="imageProcessor.h">
|
||||||
|
|||||||
@ -320,6 +320,8 @@ void TwoMotorControl::displayRealTimeLoc(std::vector<double> loc)
|
|||||||
|
|
||||||
tmp = round(loc[1] * 100) / 100;
|
tmp = round(loc[1] * 100) / 100;
|
||||||
this->ui.ymotor_realTimeLoc_lineEdit->setText(QString::number(tmp));
|
this->ui.ymotor_realTimeLoc_lineEdit->setText(QString::number(tmp));
|
||||||
|
|
||||||
|
emit broadcastLocationSignal(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwoMotorControl::zeroStart()
|
void TwoMotorControl::zeroStart()
|
||||||
|
|||||||
@ -84,6 +84,8 @@ signals:
|
|||||||
void startLineNumSignal(int lineNum);
|
void startLineNumSignal(int lineNum);
|
||||||
void sequenceComplete();//所有采集线正常运行完成
|
void sequenceComplete();//所有采集线正常运行完成
|
||||||
|
|
||||||
|
void broadcastLocationSignal(std::vector<double>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::twoMotorControl_UI ui;
|
Ui::twoMotorControl_UI ui;
|
||||||
QThread m_coordinatorThread;
|
QThread m_coordinatorThread;
|
||||||
|
|||||||
292
HPPA/View3D.cpp
Normal file
292
HPPA/View3D.cpp
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
#include "View3D.h"
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QShowEvent>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QWheelEvent>
|
||||||
|
#include <Qt3DExtras/QForwardRenderer>
|
||||||
|
#include <QtMath>
|
||||||
|
#include <Qt3DRender/QAttribute>
|
||||||
|
#include <QGeometryRenderer>
|
||||||
|
|
||||||
|
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 轴无需旋转(cylinder 默认沿 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<QMouseEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(event);
|
||||||
|
QPoint pos = e->pos();
|
||||||
|
QPoint delta = pos - m_lastMousePos;
|
||||||
|
|
||||||
|
// 左键:orbit(旋转)
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 中键:pan(平移 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<QWheelEvent*>(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<double> loc)
|
||||||
|
{
|
||||||
|
double x = round(loc[0] * 100) / 100;
|
||||||
|
double y = round(loc[1] * 100) / 100;
|
||||||
|
|
||||||
|
|
||||||
|
m_armTransform->setTranslation(QVector3D(x, y, 0));
|
||||||
|
}
|
||||||
74
HPPA/View3D.h
Normal file
74
HPPA/View3D.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#ifndef VIEW3D_H
|
||||||
|
#define VIEW3D_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QString>
|
||||||
|
#include <QQuaternion>
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
#include <Qt3DCore/QEntity>
|
||||||
|
#include <Qt3DCore/QTransform>
|
||||||
|
#include <Qt3DExtras/Qt3DWindow>
|
||||||
|
#include <Qt3DRender/QCamera>
|
||||||
|
#include <Qt3DExtras/QOrbitCameraController>
|
||||||
|
#include <Qt3DExtras/QPhongMaterial>
|
||||||
|
#include <Qt3DRender/QSceneLoader>
|
||||||
|
#include <Qt3DExtras/QCylinderMesh>
|
||||||
|
|
||||||
|
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<double> loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VIEW3D_H
|
||||||
Reference in New Issue
Block a user