对界面做了优化
This commit is contained in:
parent
517889ff90
commit
176a833bb2
6
.gitignore
vendored
6
.gitignore
vendored
@ -15,8 +15,10 @@
|
||||
Makefile*
|
||||
moc_*.cpp
|
||||
moc_*.h
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
*_resource.rc
|
||||
*_resource.res
|
||||
ui_*.h
|
||||
*.autosave
|
||||
|
||||
# 构建目录
|
||||
|
||||
@ -4,10 +4,17 @@
|
||||
QT += core
|
||||
|
||||
# 鎸囧畾椤圭洰妯℃澘涓洪潤鎬佸簱
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
|
||||
win32-msvc {
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
|
||||
win32:CONFIG(debug, debug|release) {
|
||||
DESTDIR = $$PWD/debug
|
||||
}
|
||||
win32:CONFIG(release, debug|release) {
|
||||
DESTDIR = $$PWD/release
|
||||
}
|
||||
|
||||
win32-msvc {
|
||||
QMAKE_CXXFLAGS += /utf-8
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -15,9 +15,9 @@ TEMPLATE = app
|
||||
|
||||
# 椤圭洰鐩綍
|
||||
INCLUDEPATH += $$PWD/Inc
|
||||
INCLUDEPATH += $$PWD/../../Device/SDK/VzNLSDK/Inc
|
||||
INCLUDEPATH += $$PWD/../CloudView3D/Inc
|
||||
INCLUDEPATH += $$PWD/../CloudUtils/Inc
|
||||
INCLUDEPATH += $$PWD/../../Device/SDK/VzNLSDK/Inc
|
||||
INCLUDEPATH += $$PWD/../VrUtils/Inc
|
||||
INCLUDEPATH += $$PWD/../VrCommon/Inc
|
||||
|
||||
@ -35,23 +35,28 @@ SOURCES += \
|
||||
|
||||
# 璧勬簮鏂囦欢
|
||||
RESOURCES += resource/resource.qrc
|
||||
RESOURCES += $$PWD/../../AppUtils/UICommon/common_resources.qrc
|
||||
COMMON_RESOURCES = $$PWD/../../AppUtils/UICommon/common_resources.qrc
|
||||
exists($$COMMON_RESOURCES) {
|
||||
RESOURCES += $$COMMON_RESOURCES
|
||||
} else {
|
||||
message("CloudView: optional common_resources.qrc not found; using text view buttons")
|
||||
}
|
||||
|
||||
# Windows 搴旂敤鍥炬爣
|
||||
RC_ICONS = resource/logo.ico
|
||||
|
||||
# Windows骞冲彴搴撻摼鎺?
|
||||
win32:CONFIG(release, debug|release): {
|
||||
LIBS += -L../CloudView3D/release -lCloudView3D
|
||||
LIBS += -L../CloudUtils/release -lCloudUtils
|
||||
LIBS += -L../VrUtils/release -lVrUtils
|
||||
LIBS += -L../VrCommon/release -lVrCommon
|
||||
LIBS += -L$$PWD/../CloudView3D/release -lCloudView3D
|
||||
LIBS += -L$$PWD/../CloudUtils/release -lCloudUtils
|
||||
LIBS += -L$$PWD/../VrUtils/release -lVrUtils
|
||||
LIBS += -L$$PWD/../VrCommon/release -lVrCommon
|
||||
}
|
||||
else:win32:CONFIG(debug, debug|release): {
|
||||
LIBS += -L../CloudView3D/debug -lCloudView3D
|
||||
LIBS += -L../CloudUtils/debug -lCloudUtils
|
||||
LIBS += -L../VrUtils/debug -lVrUtils
|
||||
LIBS += -L../VrCommon/debug -lVrCommon
|
||||
LIBS += -L$$PWD/../CloudView3D/debug -lCloudView3D
|
||||
LIBS += -L$$PWD/../CloudUtils/debug -lCloudUtils
|
||||
LIBS += -L$$PWD/../VrUtils/debug -lVrUtils
|
||||
LIBS += -L$$PWD/../VrCommon/debug -lVrCommon
|
||||
}
|
||||
|
||||
# Windows绯荤粺搴?
|
||||
|
||||
@ -1357,32 +1357,38 @@ QWidget* CloudViewMainWindow::createViewToolbar()
|
||||
layout->setSpacing(3);
|
||||
|
||||
// 视图预设:图标、提示、旋转角度
|
||||
struct ViewPreset {
|
||||
const char* iconPath;
|
||||
const char* tooltip;
|
||||
struct ViewPreset {
|
||||
const char* iconPath;
|
||||
const char* fallbackText;
|
||||
const char* tooltip;
|
||||
float rotX;
|
||||
float rotY;
|
||||
float rotZ;
|
||||
};
|
||||
|
||||
// 坐标系定义:X向右,Y向下,Z朝后
|
||||
ViewPreset presets[] = {
|
||||
{":/common/resource/view_front.png", "正视 (XY面)", 180.0f, 0.0f, 0.0f},
|
||||
{":/common/resource/view_back.png", "后视", 180.0f, 180.0f, 0.0f},
|
||||
{":/common/resource/view_left.png", "左视 (YZ面)", 180.0f, 90.0f, 0.0f},
|
||||
{":/common/resource/view_right.png", "右视", 180.0f, -90.0f, 0.0f},
|
||||
{":/common/resource/view_top.png", "俯视 (XZ面)", 90.0f, 0.0f, 0.0f},
|
||||
{":/common/resource/view_bottom.png", "仰视", -90.0f, 0.0f, 0.0f},
|
||||
{":/common/resource/view_robot.png", "机械臂", -90.0f, 90.0f, 0.0f},
|
||||
};
|
||||
// 坐标系定义:X向右,Y向下,Z朝后
|
||||
ViewPreset presets[] = {
|
||||
{":/common/resource/view_front.png", "前", "正视 (XY面)", 180.0f, 0.0f, 0.0f},
|
||||
{":/common/resource/view_back.png", "后", "后视", 180.0f, 180.0f, 0.0f},
|
||||
{":/common/resource/view_left.png", "左", "左视 (YZ面)", 180.0f, 90.0f, 0.0f},
|
||||
{":/common/resource/view_right.png", "右", "右视", 180.0f, -90.0f, 0.0f},
|
||||
{":/common/resource/view_top.png", "上", "俯视 (XZ面)", 90.0f, 0.0f, 0.0f},
|
||||
{":/common/resource/view_bottom.png", "下", "仰视", -90.0f, 0.0f, 0.0f},
|
||||
{":/common/resource/view_robot.png", "机", "机械臂", -90.0f, 90.0f, 0.0f},
|
||||
};
|
||||
|
||||
int btnSize = 32;
|
||||
int iconSize = 24;
|
||||
|
||||
for (const auto& preset : presets) {
|
||||
QToolButton* btn = new QToolButton(widget);
|
||||
btn->setIcon(QIcon(preset.iconPath));
|
||||
btn->setIconSize(QSize(iconSize, iconSize));
|
||||
for (const auto& preset : presets) {
|
||||
QToolButton* btn = new QToolButton(widget);
|
||||
const QIcon icon(preset.iconPath);
|
||||
if (icon.isNull()) {
|
||||
btn->setText(QString::fromUtf8(preset.fallbackText));
|
||||
} else {
|
||||
btn->setIcon(icon);
|
||||
btn->setIconSize(QSize(iconSize, iconSize));
|
||||
}
|
||||
btn->setFixedSize(btnSize, btnSize);
|
||||
btn->setToolTip(preset.tooltip);
|
||||
btn->setAutoRaise(true);
|
||||
@ -2379,6 +2385,7 @@ void CloudViewMainWindow::showBasicShape(const QString& shapeName,
|
||||
if (!points.isEmpty()) {
|
||||
m_glWidget->appendBasicShapePoints(points);
|
||||
}
|
||||
m_glWidget->fitToContent();
|
||||
statusBar()->showMessage(QString("已添加 %1").arg(shapeName));
|
||||
LOG_INFO("[CloudView] Add basic shape: %s, segments=%d, points=%d\n",
|
||||
shapeName.toStdString().c_str(), segments.size(), points.size());
|
||||
@ -2392,6 +2399,7 @@ void CloudViewMainWindow::showBasicSurface(const QString& shapeName, const QVect
|
||||
|
||||
m_glWidget->appendBasicShapeSurfaces(surfaces);
|
||||
m_glWidget->appendBasicShapeSegments(outlines);
|
||||
m_glWidget->fitToContent();
|
||||
statusBar()->showMessage(QString("已添加 %1").arg(shapeName));
|
||||
LOG_INFO("[CloudView] Add basic surface: %s, surfaces=%d, outlines=%d\n",
|
||||
shapeName.toStdString().c_str(), surfaces.size(), outlines.size());
|
||||
|
||||
@ -65,6 +65,14 @@ int main(int argc, char* argv[])
|
||||
parser.addOption(triangleOption);
|
||||
parser.addOption(sequenceOption);
|
||||
parser.addPositionalArgument("files", "Point cloud or segment files to load.");
|
||||
if (app.arguments().contains(QStringLiteral("--help")) ||
|
||||
app.arguments().contains(QStringLiteral("-h"))) {
|
||||
parser.showHelp(0);
|
||||
}
|
||||
if (app.arguments().contains(QStringLiteral("--version")) ||
|
||||
app.arguments().contains(QStringLiteral("-v"))) {
|
||||
parser.showVersion();
|
||||
}
|
||||
parser.process(app);
|
||||
|
||||
CloudViewMainWindow::StartupFiles startupFiles;
|
||||
|
||||
@ -4,6 +4,13 @@ CONFIG += c++17 staticlib
|
||||
TEMPLATE = lib
|
||||
TARGET = CloudView3D
|
||||
|
||||
win32:CONFIG(debug, debug|release) {
|
||||
DESTDIR = $$PWD/debug
|
||||
}
|
||||
win32:CONFIG(release, debug|release) {
|
||||
DESTDIR = $$PWD/release
|
||||
}
|
||||
|
||||
win32-msvc {
|
||||
QMAKE_CXXFLAGS += /utf-8
|
||||
QMAKE_CXXFLAGS += /bigobj
|
||||
@ -11,8 +18,8 @@ win32-msvc {
|
||||
|
||||
INCLUDEPATH += $$PWD/Inc
|
||||
INCLUDEPATH += $$PWD/../VrUtils/Inc
|
||||
INCLUDEPATH += $$PWD/../VrCommon/Inc
|
||||
INCLUDEPATH += $$PWD/../../Device/SDK/VzNLSDK/Inc
|
||||
INCLUDEPATH += $$PWD/../VrCommon/Inc
|
||||
|
||||
HEADERS += \
|
||||
Inc/CloudView3D.h \
|
||||
|
||||
@ -168,9 +168,10 @@ public:
|
||||
explicit PointCloudGLWidget(QWidget* parent = nullptr);
|
||||
~PointCloudGLWidget() override;
|
||||
|
||||
void addPointCloud(const PointCloudXYZ& cloud, const QString& name = "");
|
||||
void addPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "");
|
||||
void clearPointClouds();
|
||||
void addPointCloud(const PointCloudXYZ& cloud, const QString& name = "");
|
||||
void addPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "");
|
||||
void appendPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "");
|
||||
void clearPointClouds();
|
||||
void setPointCloudColor(PointCloudColor color);
|
||||
void setPointSize(float size);
|
||||
void resetView();
|
||||
@ -454,8 +455,10 @@ private:
|
||||
PointCloudData& operator=(const PointCloudData&) = delete;
|
||||
};
|
||||
|
||||
void computeBoundingBox();
|
||||
void setCurrentColor(PointCloudColor color);
|
||||
void computeBoundingBox();
|
||||
void updateProjection(const QMatrix4x4& modelView);
|
||||
float minimumCameraDistance() const;
|
||||
void setCurrentColor(PointCloudColor color);
|
||||
void setColorByIndex(int colorIndex); // 根据索引设置颜色
|
||||
SelectedPointInfo pickPoint(int screenX, int screenY);
|
||||
void drawSelectedPoints();
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
#include "PointCloudGLWidget.h"
|
||||
#include <QDebug>
|
||||
#include <QtMath>
|
||||
#include <QPainter>
|
||||
#include <cfloat>
|
||||
#include <QDebug>
|
||||
#include <QtMath>
|
||||
#include <QPainter>
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <map>
|
||||
#include "VrLog.h"
|
||||
|
||||
@ -113,16 +114,10 @@ void PointCloudGLWidget::initializeGL()
|
||||
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::resizeGL(int w, int h)
|
||||
{
|
||||
glViewport(0, 0, w, h);
|
||||
|
||||
m_projection.setToIdentity();
|
||||
float aspect = static_cast<float>(w) / static_cast<float>(h > 0 ? h : 1);
|
||||
// 放大裁剪范围以容纳激光雷达点云(最大可能跨越数十万 mm)
|
||||
// near 取 1.0 保留 depth buffer 精度,far 放到 1e7 避免远点被裁掉
|
||||
m_projection.perspective(45.0f, aspect, 1.0f, 1.0e7f);
|
||||
}
|
||||
void PointCloudGLWidget::resizeGL(int w, int h)
|
||||
{
|
||||
glViewport(0, 0, w, h);
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::paintGL()
|
||||
{
|
||||
@ -146,12 +141,14 @@ void PointCloudGLWidget::paintGL()
|
||||
euler.x(), euler.y(), euler.z());
|
||||
}
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(m_projection.constData());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
QMatrix4x4 modelView = m_view * m_model;
|
||||
glLoadMatrixf(modelView.constData());
|
||||
QMatrix4x4 modelView = m_view * m_model;
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
updateProjection(modelView);
|
||||
glLoadMatrixf(m_projection.constData());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(modelView.constData());
|
||||
|
||||
// 确保颜色数组禁用
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
@ -330,8 +327,8 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZ& cloud, const QString
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QString& name)
|
||||
{
|
||||
void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QString& name)
|
||||
{
|
||||
if (cloud.empty()) {
|
||||
return;
|
||||
}
|
||||
@ -437,10 +434,105 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
|
||||
|
||||
computeBoundingBox();
|
||||
resetView();
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::clearPointClouds()
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::appendPointCloud(const PointCloudXYZRGB& cloud,
|
||||
const QString& name)
|
||||
{
|
||||
if (cloud.empty()) {
|
||||
return;
|
||||
}
|
||||
if (m_pointClouds.empty() || !m_pointClouds.back().hasColor) {
|
||||
addPointCloud(cloud, name);
|
||||
return;
|
||||
}
|
||||
|
||||
PointCloudData& data = m_pointClouds.back();
|
||||
if (!name.isEmpty()) {
|
||||
data.name = name;
|
||||
}
|
||||
|
||||
const bool incomingHasLineInfo = !cloud.lineIndices.empty();
|
||||
data.hasLineInfo = data.hasLineInfo || incomingHasLineInfo;
|
||||
const size_t originalIndexOffset = data.vertices.size() / 3;
|
||||
const float epsilon = 1e-6f;
|
||||
int previousLineIndex = -1;
|
||||
int pointInLineIndex = 0;
|
||||
|
||||
for (size_t index = 0; index < cloud.points.size(); ++index) {
|
||||
const Point3DRGB& point = cloud.points[index];
|
||||
int lineIndex = -1;
|
||||
if (incomingHasLineInfo && index < cloud.lineIndices.size()) {
|
||||
lineIndex = cloud.lineIndices[index];
|
||||
}
|
||||
if (lineIndex != previousLineIndex) {
|
||||
pointInLineIndex = 0;
|
||||
previousLineIndex = lineIndex;
|
||||
}
|
||||
|
||||
if (!std::isfinite(point.x) || !std::isfinite(point.y) ||
|
||||
!std::isfinite(point.z) ||
|
||||
(std::fabs(point.x) < epsilon &&
|
||||
std::fabs(point.y) < epsilon &&
|
||||
std::fabs(point.z) < epsilon)) {
|
||||
++pointInLineIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t pointIndex = data.vertices.size() / 3;
|
||||
data.vertices.push_back(point.x);
|
||||
data.vertices.push_back(point.y);
|
||||
data.vertices.push_back(point.z);
|
||||
data.colors.push_back(point.r / 255.0f);
|
||||
data.colors.push_back(point.g / 255.0f);
|
||||
data.colors.push_back(point.b / 255.0f);
|
||||
data.originalIndices.push_back(
|
||||
static_cast<int>(originalIndexOffset + index));
|
||||
data.pointInLineIndices.push_back(pointInLineIndex);
|
||||
|
||||
if (lineIndex >= 0) {
|
||||
data.lineIndices.push_back(lineIndex);
|
||||
data.totalLines = qMax(data.totalLines, lineIndex + 1);
|
||||
}
|
||||
|
||||
if (point.pointSize > 1.0f) {
|
||||
auto sizeGroup = std::find_if(
|
||||
data.customPointSizeGroups.begin(),
|
||||
data.customPointSizeGroups.end(),
|
||||
[&point](const PointCloudData::PointSizeGroup& group) {
|
||||
return group.pointSize == point.pointSize;
|
||||
});
|
||||
if (sizeGroup == data.customPointSizeGroups.end()) {
|
||||
PointCloudData::PointSizeGroup group;
|
||||
group.pointSize = point.pointSize;
|
||||
data.customPointSizeGroups.push_back(std::move(group));
|
||||
sizeGroup = data.customPointSizeGroups.end() - 1;
|
||||
}
|
||||
sizeGroup->indices.push_back(pointIndex);
|
||||
data.hasCustomPointSizes = true;
|
||||
}
|
||||
++pointInLineIndex;
|
||||
}
|
||||
|
||||
if (data.totalLines > 0) {
|
||||
data.pointsPerLine =
|
||||
static_cast<int>(data.vertices.size() / 3) / data.totalLines;
|
||||
}
|
||||
|
||||
makeCurrent();
|
||||
uploadToVBO(data);
|
||||
doneCurrent();
|
||||
|
||||
computeBoundingBox();
|
||||
const QVector3D size = m_maxBound - m_minBound;
|
||||
const float maximumSize = qMax(qMax(size.x(), size.y()), size.z());
|
||||
m_distance = qMax(m_distance,
|
||||
qBound(10.0f, maximumSize * 2.5f, 1.0e7f));
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::clearPointClouds()
|
||||
{
|
||||
// 释放所有 VBO
|
||||
makeCurrent();
|
||||
@ -506,19 +598,83 @@ void PointCloudGLWidget::fitToContent()
|
||||
resetView();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::updateProjection(const QMatrix4x4& modelView)
|
||||
{
|
||||
const QVector3D corners[] = {
|
||||
{m_minBound.x(), m_minBound.y(), m_minBound.z()},
|
||||
{m_minBound.x(), m_minBound.y(), m_maxBound.z()},
|
||||
{m_minBound.x(), m_maxBound.y(), m_minBound.z()},
|
||||
{m_minBound.x(), m_maxBound.y(), m_maxBound.z()},
|
||||
{m_maxBound.x(), m_minBound.y(), m_minBound.z()},
|
||||
{m_maxBound.x(), m_minBound.y(), m_maxBound.z()},
|
||||
{m_maxBound.x(), m_maxBound.y(), m_minBound.z()},
|
||||
{m_maxBound.x(), m_maxBound.y(), m_maxBound.z()}
|
||||
};
|
||||
|
||||
float minimumDepth = FLT_MAX;
|
||||
float maximumDepth = -FLT_MAX;
|
||||
for (const QVector3D& corner : corners) {
|
||||
const float depth = -modelView.map(corner).z();
|
||||
minimumDepth = qMin(minimumDepth, depth);
|
||||
maximumDepth = qMax(maximumDepth, depth);
|
||||
}
|
||||
|
||||
constexpr float kMinimumNearPlane = 0.01f;
|
||||
float nearPlane = kMinimumNearPlane;
|
||||
float farPlane = 1.0f;
|
||||
if (maximumDepth > kMinimumNearPlane) {
|
||||
// 点云贴近或跨过相机时保持很小的近裁剪距离,避免前侧点被裁掉。
|
||||
if (minimumDepth > kMinimumNearPlane) {
|
||||
nearPlane = qMax(kMinimumNearPlane, minimumDepth * 0.5f);
|
||||
}
|
||||
// 远裁剪面仅覆盖当前内容,并限制 near/far 比值以保证深度缓冲精度。
|
||||
farPlane = qMax(nearPlane + 1.0f, maximumDepth * 1.5f);
|
||||
nearPlane = qMax(nearPlane, farPlane / 100000.0f);
|
||||
}
|
||||
|
||||
const float aspect = static_cast<float>(width()) /
|
||||
static_cast<float>(height() > 0 ? height() : 1);
|
||||
m_projection.setToIdentity();
|
||||
m_projection.perspective(45.0f, aspect, nearPlane, farPlane);
|
||||
}
|
||||
|
||||
float PointCloudGLWidget::minimumCameraDistance() const
|
||||
{
|
||||
const QVector3D corners[] = {
|
||||
{m_minBound.x(), m_minBound.y(), m_minBound.z()},
|
||||
{m_minBound.x(), m_minBound.y(), m_maxBound.z()},
|
||||
{m_minBound.x(), m_maxBound.y(), m_minBound.z()},
|
||||
{m_minBound.x(), m_maxBound.y(), m_maxBound.z()},
|
||||
{m_maxBound.x(), m_minBound.y(), m_minBound.z()},
|
||||
{m_maxBound.x(), m_minBound.y(), m_maxBound.z()},
|
||||
{m_maxBound.x(), m_maxBound.y(), m_minBound.z()},
|
||||
{m_maxBound.x(), m_maxBound.y(), m_maxBound.z()}
|
||||
};
|
||||
|
||||
float frontExtent = 0.0f;
|
||||
for (const QVector3D& corner : corners) {
|
||||
const QVector3D relativePosition = corner - m_center;
|
||||
frontExtent = qMax(frontExtent,
|
||||
m_rotation.rotatedVector(relativePosition).z());
|
||||
}
|
||||
|
||||
const float margin = qMax(0.1f, (m_maxBound - m_minBound).length() * 0.002f);
|
||||
return qBound(0.1f, frontExtent + margin, 1.0e7f);
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::zoomIn()
|
||||
{
|
||||
m_distance *= 0.9f;
|
||||
m_distance = qBound(0.1f, m_distance, 1.0e7f);
|
||||
update();
|
||||
}
|
||||
m_distance = qBound(minimumCameraDistance(), m_distance, 1.0e7f);
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::zoomOut()
|
||||
{
|
||||
m_distance *= 1.1f;
|
||||
m_distance = qBound(0.1f, m_distance, 1.0e7f);
|
||||
update();
|
||||
}
|
||||
{
|
||||
m_distance *= 1.1f;
|
||||
m_distance = qBound(minimumCameraDistance(), m_distance, 1.0e7f);
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::setViewAngles(float rotX, float rotY, float rotZ)
|
||||
{
|
||||
@ -527,8 +683,9 @@ void PointCloudGLWidget::setViewAngles(float rotX, float rotY, float rotZ)
|
||||
m_rotationZ = rotZ;
|
||||
m_pan = QVector3D(0, 0, 0);
|
||||
|
||||
// 从欧拉角转换为四元数(ZYX顺序)
|
||||
m_rotation = QQuaternion::fromEulerAngles(rotX, rotY, rotZ);
|
||||
// 从欧拉角转换为四元数(ZYX顺序)
|
||||
m_rotation = QQuaternion::fromEulerAngles(rotX, rotY, rotZ);
|
||||
m_distance = qMax(m_distance, minimumCameraDistance());
|
||||
|
||||
LOG_INFO("[CloudView] setViewAngles: rotX=%.1f, rotY=%.1f, rotZ=%.1f\n", rotX, rotY, rotZ);
|
||||
|
||||
@ -1440,8 +1597,9 @@ void PointCloudGLWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
m_rotationY += angleY;
|
||||
}
|
||||
|
||||
// 发送角度变化信号
|
||||
emit viewAnglesChanged(m_rotationX, m_rotationY, m_rotationZ);
|
||||
// 发送角度变化信号
|
||||
m_distance = qMax(m_distance, minimumCameraDistance());
|
||||
emit viewAnglesChanged(m_rotationX, m_rotationY, m_rotationZ);
|
||||
update();
|
||||
} else if (m_middleButtonPressed) {
|
||||
float factor = m_distance * 0.002f;
|
||||
@ -1452,9 +1610,10 @@ void PointCloudGLWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
// 右键拖动:绕视线方向旋转(滚转)(修正方向)
|
||||
float angle = -delta.x() * 0.5f; // 取反修正方向
|
||||
QQuaternion deltaRotation = QQuaternion::fromAxisAndAngle(QVector3D(0, 0, 1), angle);
|
||||
m_rotation = deltaRotation * m_rotation;
|
||||
m_rotationZ += angle;
|
||||
emit viewAnglesChanged(m_rotationX, m_rotationY, m_rotationZ);
|
||||
m_rotation = deltaRotation * m_rotation;
|
||||
m_rotationZ += angle;
|
||||
m_distance = qMax(m_distance, minimumCameraDistance());
|
||||
emit viewAnglesChanged(m_rotationX, m_rotationY, m_rotationZ);
|
||||
update();
|
||||
}
|
||||
}
|
||||
@ -1472,11 +1631,11 @@ void PointCloudGLWidget::mouseReleaseEvent(QMouseEvent* event)
|
||||
|
||||
void PointCloudGLWidget::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
float delta = event->angleDelta().y() / 120.0f;
|
||||
m_distance *= (1.0f - delta * 0.1f);
|
||||
m_distance = qBound(0.1f, m_distance, 1.0e7f);
|
||||
update();
|
||||
}
|
||||
float delta = event->angleDelta().y() / 120.0f;
|
||||
m_distance *= (1.0f - delta * 0.1f);
|
||||
m_distance = qBound(minimumCameraDistance(), m_distance, 1.0e7f);
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
|
||||
@ -1,10 +1,17 @@
|
||||
#CONFIG -= qt
|
||||
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
CONFIG += c++17
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
CONFIG += c++17
|
||||
|
||||
win32:CONFIG(debug, debug|release) {
|
||||
DESTDIR = $$PWD/debug
|
||||
}
|
||||
win32:CONFIG(release, debug|release) {
|
||||
DESTDIR = $$PWD/release
|
||||
}
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
|
||||
@ -6,9 +6,16 @@ DEFINES += TINYXML2_EXPORT
|
||||
DEFINES += HAVE_SNPRINTF
|
||||
DEFINES += LOG4CPP_HAVE_SSTREAM=1
|
||||
DEFINES += VR_UTILS_EXPORTS
|
||||
CONFIG += c++11
|
||||
|
||||
# Unix平台特定配置
|
||||
CONFIG += c++11
|
||||
|
||||
win32:CONFIG(debug, debug|release) {
|
||||
DESTDIR = $$PWD/debug
|
||||
}
|
||||
win32:CONFIG(release, debug|release) {
|
||||
DESTDIR = $$PWD/release
|
||||
}
|
||||
|
||||
# Unix平台特定配置
|
||||
unix:!macx {
|
||||
DEFINES += LOG4CPP_HAVE_UNISTD_H
|
||||
# 确保所有符号导出(对于静态库)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user