first commit

This commit is contained in:
2025-12-18 09:19:39 +08:00
parent 1bc7adf399
commit d4975da9a5
24 changed files with 2506 additions and 0 deletions

151
src/glwidget.h Normal file
View File

@@ -0,0 +1,151 @@
//
// Created by Lenn on 2025/12/16.
//
#ifndef TACTILEIPC3D_GLWIDGET_H
#define TACTILEIPC3D_GLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QMutex>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions_3_3_Core>
#include <QMatrix4x4>
#include <QVector3D>
#include <QString>
#include <atomic>
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
Q_OBJECT
Q_PROPERTY(float yaw READ yaw WRITE setYaw NOTIFY yawChanged)
public:
enum RenderMode {
Realistic = 0,
DataViz = 1,
};
Q_ENUM(RenderMode)
enum LabelMode {
LabelsOff = 0,
LabelsHover = 1,
LabelsAlways = 2,
};
Q_ENUM(LabelMode)
explicit GLWidget(QWidget* parent = nullptr);
~GLWidget();
// panel 的物理尺寸(单位随你:米/毫米都行,只要全程一致)
void setPanelSize(float w, float h, float d);
void setPanelThickness(float h);
// rows/cols: 传感点阵行列pitch: 点与点的间距dotRaius: 单个点的“显示半径”
void setSpec(int rows, int cols, float pitch, float dotRaius);
// 总点数 = 行 * 列
int dotCount() const { return m_cols * m_rows; }
// 提交一帧传感值(数量必须等于 dotCount在 paintGL 里用 instanced 的方式绘制
void submitValues(const QVector<float>& values);
float yaw() const { return m_camYawDeg; }
public slots:
// 值域范围,用于 shader 里把 value 映射到颜色(绿->红)
void setRange(int minV, int maxV);
void setYaw(float yawDeg);
void setRenderModeString(const QString& mode);
void setLabelModeString(const QString& mode);
signals:
void yawChanged();
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
private:
void initPanelGeometry_();
void initDotGeometry_();
void initBackgroundGeometry_();
void initPrograms_();
void initDotTexture_();
void updateInstanceBufferIfNeeded_();
void updateMatrices_();
private:
// 传感值范围(用于颜色映射)
int m_min = 0;
int m_max = 1000;
// 点阵规格
int m_rows = 3;
int m_cols = 4;
// panel: 一个长方体/板子(当前只画顶面矩形)
float m_panelW = 1.2f;
float m_panelH = 0.08f;
float m_panelD = 0.08f;
// 点阵布局参数
float m_pitch = 0.1f;
float m_dotRadius = 0.03f;
// 传感数据GUI/定时器线程提交GL 线程绘制)
QMutex m_dataMutex;
QVector<float> m_latestValues;
bool m_valuesDirty = false;
std::atomic<bool> m_hasData{false};
// shader program编译/链接后的可执行 GPU 程序)
QOpenGLShaderProgram* m_bgProg = nullptr;
QOpenGLShaderProgram* m_panelProg = nullptr;
QOpenGLShaderProgram* m_dotsProg = nullptr;
unsigned int m_dotTex = 0;
// panel 的 VAO/VBO/IBOVAO: 顶点格式/绑定状态VBO: 顶点数据IBO: 索引数据)
unsigned int m_panelVao = 0;
unsigned int m_panelVbo = 0;
unsigned int m_panelIbo = 0;
int m_panelIndexCount = 0;
bool m_panelGeometryDirty = false;
// dots 的 VAO/VBO + instance VBOinstance VBO 每个点一条offsetXZ + value
unsigned int m_dotsVao = 0;
unsigned int m_dotsVbo = 0;
unsigned int m_instanceVbo = 0;
int m_instanceCount = 0;
bool m_dotsGeometryDirty = false;
unsigned int m_bgVao = 0;
unsigned int m_bgVbo = 0;
// MVP = Projection * View * Model。
// 这里 panel/dots 顶点基本已经是“世界坐标”,所以我们用 proj*view 即可model 先省略)。
QMatrix4x4 m_mvp;
QVector3D m_cameraPos{0.0f, 0.0f, 1.0f};
RenderMode m_renderMode = DataViz;
LabelMode m_labelMode = LabelsOff;
int m_hoveredIndex = -1;
// 早期/预留的矩阵数组(现在主要使用 QMatrix4x4 的 m_mvp这些暂时保留做对照/扩展)
float m_proj[16]{};
float m_view[16]{};
float m_modelPanel[16]{};
float m_zoom_ = 45.0;
float m_camYawDeg = 45.0f;
float m_camPitchDeg = 35.0f;
std::atomic<bool> m_rightDown{false};
QPoint m_lastPos;
};
#endif //TACTILEIPC3D_GLWIDGET_H