qt+opengl 三维物体加入摄像机

news2024/11/24 22:09:27

1 在前几期的文章中,我们已经实现了三维正方体的显示了,那我们来实现让物体的由远及近,和由近及远。这里我们需要了解一个概念摄像机。

1.1 摄像机定义:在世界空间中位置观察方向指向右侧向量指向上方的向量。如下图所示:

 1.2 实现一个摄像机

首先定义一个摄像机位置,然后获取一个摄影机指向原点的向量,并且获取指向摄像机的单位向量(只关心摄像机的方向,不关心其长度).代码如下所示:

  1. QVector3D cameraPos(0, 0, 3)

  2. QVector3D cameraTarget(0, 0, 0);

  3. QVector3D cameraDirection( (cameraTarget- cameraPos).normalized() )

1.3 摄像机位置

摄像机位置是在世界空间中一个指向摄像机位置的向量。右手坐标系:大拇指指向正x轴方向,食指指向正y轴方向,中指指向正z轴方向,z正轴从屏幕指向自己。

 通过改变摄像机的位置就可以实现物体的远近效果。

在qt opengl 函数里面我们有函数实现了

void QMatrix4x4::lookAt(const QVector3D &eye, const QVector3D &center, const QVector3D &up)
//获取lookAt矩阵.
//eye: 设置摄像机(眼睛)位置,比如QVector3D(0,0,3)
//center:表示摄像机(眼睛)正在看的视图的中心,比如原点QVector3D(0,0,0)
//up:眼睛的上向量,一般为QVector3D(0,1,0),通过该向量就能获取到眼睛的右轴和上轴

 这里我们只需要设置相应的参数就可以了

eye : 就是我们眼睛的位置,这里我们设置Z轴正方向 QVector3D(0, 0, 3);

center : 就是我们以什么地方为中心点观察物体,如QVector3D(0, 0, 0);原点。

up:眼睛的上向量,一般为QVector3D(0,1,0),通过该向量就能获取到眼睛的右轴和上轴

好了,那么我们现在来修改glsl语句和代码实现。

#include "glwidget.h"
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QMouseEvent>
#include <QDateTime>
#include <QtMath>

static const char *vertexShaderSource =
    "#version 330\n"
    "layout (location = 0) in vec4 vertex;\n"
    "layout (location = 1) in vec4 texCoord;\n"
    "out vec4 texc;\n"
    "uniform  mat4 matrix;\n"
    "uniform  mat4 model;\n"
    "uniform  mat4 view;\n"
    "uniform  mat4 projection;\n"
    "void main(void)\n"
    "{\n"
    "    gl_Position =  projection*view* matrix * vertex;\n"
    "    texc = texCoord;\n"
    "}\n";

static const char *fragmentShaderSource =
      "#version 330\n"
      "uniform sampler2D texture;\n"
      "in vec4 texc;\n"
      "void main(void)\n"
      "{\n"
      "    gl_FragColor = texture2D(texture, texc.st);\n"
      "}\n";

GLWidget::GLWidget():QOpenGLWidget()
  ,m_xRos(0)
  ,m_yRos(0)
{
    cam = QVector3D(m_xRos, m_yRos, m_zRos);

    cameraPos = QVector3D(0, 0, 3); 近---远
   // cameraPos = QVector3D(0, 0, 30);远---近

    timer = new QTimer;
    timer->setInterval(20);
    connect(timer,&QTimer::timeout,this,[=]{
        qDebug()<<"timeout"<<nCount<<m_xRos;

       rotateBy(2 * 16, +2 * 16, -1 * 16);
    });

}
GLWidget::~GLWidget()
{
    makeCurrent();
    vbo.destroy();
    for (int i = 0; i < 6; ++i)
        delete textures[i];
    delete program;
    doneCurrent();
}

QSize GLWidget::minimumSizeHint() const
{
    return QSize(400, 400);
}

QSize GLWidget::sizeHint() const
{
    return QSize(400, 400);
}

void GLWidget::rotateBy(int xAngle, int yAngle, int zAngle)
{
    float cameraSpeed = 0.2;
    cameraPos += cameraSpeed * QVector3D(0, 0, 1);//由远到近
    //cameraPos -= cameraSpeed * QVector3D(0, 0, 1);//由近到远

    xRot += xAngle;
    yRot += yAngle;
    zRot += zAngle;
    update();
}

void GLWidget::setClearColor(const QColor &color)
{
    clearColor = color;
    update();
}

void GLWidget::initializeGL()
{
    vertices = {
            // ---- 位置----   - 纹理坐标 -      ---- 颜色 ----

        0.5f, -0.5f, -0.5f,   1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, 0.5f, -0.5f,   0.0f, 0.0f,
        0.5f, 0.5f, -0.5f,   1.0f, 0.0f,//1

        0.5f, 0.5f, -0.5f,   1.0f, 1.0f,
        -0.5f, 0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, 0.5f, 0.5f,   0.0f, 0.0f,
        0.5f, 0.5f, 0.5f,    1.0f, 0.0f,//2


        0.5f, -0.5f, 0.5f,   1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, 0.5f, -0.5f,   0.0f, 0.0f,
        0.5f, 0.5f, 0.5f,    1.0f, 0.0f,//3



        -0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         -0.5f, -0.5f, 0.5f,  0.0f, 1.0f,
         -0.5f, 0.5f, 0.5f,   0.0f, 0.0f,
        -0.5f, 0.5f, -0.5f,   1.0f, 0.0f,//4


         0.5f, -0.5f, 0.5f,   1.0f, 1.0f,
         -0.5f, -0.5f, 0.5f,  0.0f, 1.0f,
         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,//5

        -0.5f, -0.5f, 0.5f,   1.0f, 1.0f,
         0.5f, -0.5f, 0.5f,   0.0f, 1.0f,
         0.5f, 0.5f, 0.5f,    0.0f, 0.0f,
        -0.5f, 0.5f, 0.5f,    1.0f, 0.0f,

    };
    initializeOpenGLFunctions();

   // makeObject();

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

//#define PROGRAM_VERTEX_ATTRIBUTE 0
//#define PROGRAM_TEXCOORD_ATTRIBUTE 1

    program = new QOpenGLShaderProgram;
    program->addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);
    program->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);
    program->link();
    program->bind();//激活Program对象

    vbo.create();
    vbo.bind();              //绑定到当前的OpenGL上下文,
    vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));


    //初始化VAO,设置顶点数据状态(顶点,法线,纹理坐标等)
    vao.create();
    vao.bind();

    for (int j = 0; j < 6; ++j)
    {
        textures[j] = new QOpenGLTexture(QImage(QString(":/cube%1.png").arg(j + 1)).mirrored());
        textures[j]->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);
        textures[j]->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);
        textures[j]->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);
    }
    program->setAttributeBuffer(0, GL_FLOAT, 0,                  3, 5 * sizeof(float));   //设置aPos顶点属性
    program->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float),  2, 5 * sizeof(float));   //设置aColor顶点颜色
    program->enableAttributeArray(0); //使能aPos顶点属性
    program->enableAttributeArray(1); //使能aColor顶点颜色
    program->setUniformValue("texture", 0);
    QMatrix4x4 projection;
    projection.perspective(60,(float)width()/height(),0.1,100);//构建透视矩阵,这个可以是固定写法
    program->setUniformValue("projection", projection);

//    vao.release();
//    vbo.release();
}

void GLWidget::paintGL()
{
    //glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.1f,0.5f,0.7f,1.0f);  //设置清屏颜色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 m;
    //m.ortho(-0.5f, +0.5f, +0.5f, -0.5f, 4.0f, 15.0f);
    m.translate(0.0f, 0.0f, 0.0f);
    m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);
    m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);
    m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);
    m.scale(0.5);
    program->setUniformValue("matrix", m);

//    QMatrix4x4 view;
//    view.translate(0.0f,0.0f,-3.0f);
//    program->setUniformValue("view", view);


    QMatrix4x4 view;
    view.lookAt(cameraPos, QVector3D(0, 0, 0), QVector3D(0, 1, 0));
    //view.lookAt(cameraPos, cameraPos+QVector3D(0,0,-1), QVector3D(0,1,0));
    program->setUniformValue("view", view);

    for (int i = 0; i < 6; ++i) {
        textures[i]->bind();
        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
    }
}
void GLWidget::resizeGL(int width, int height)
{
    this->glViewport(0,0,width,height);                //定义视口区域
}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
    timer->start();
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();

    if (event->buttons() & Qt::LeftButton) {
        rotateBy(8 * dy, 8 * dx, 0);
    } else if (event->buttons() & Qt::RightButton) {
        rotateBy(8 * dy, 0, 8 * dx);
    }
    lastPos = event->pos();
}

void GLWidget::mouseReleaseEvent(QMouseEvent * /* event */)
{
    emit clicked();
}

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QTimer>
#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>


QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram);
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)

class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    //using QOpenGLWidget::QOpenGLWidget;
    GLWidget();
    ~GLWidget();

    QSize minimumSizeHint() const override;
    QSize sizeHint() const override;
    void rotateBy(int xAngle, int yAngle, int zAngle);
    void setClearColor(const QColor &color);

signals:
    void clicked();

protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int width, int height) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

private:

    QColor clearColor = Qt::black;
    QPoint lastPos;
    int xRot = 0;
    int yRot = 0;
    int zRot = 0;
    QOpenGLTexture *textures[6] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
    QOpenGLShaderProgram *program = nullptr;
    QOpenGLBuffer vbo;
    QVector<float> vertices;
    QOpenGLVertexArrayObject vao;
    QTimer* timer;
    float m_xRos = 0.0f;
    float m_yRos = 0.0f;
    float m_zRos = 3.0f;
    QVector3D   cam;
    int nCount=0;

    QVector3D cameraPos;

    QVector3D cameraTarget;

    QVector3D cameraDirection;
};

#endif

 运行下代码是不是就是可以由远到近和由近到远了呢.

我们初始化

cameraPos = QVector3D(0, 0, 3);    
cameraPos += cameraSpeed * QVector3D(0, 0, 1);//由近到远

这样写就是近--远了呢

cameraPos = QVector3D(0, 0, 30);
cameraPos -= cameraSpeed * QVector3D(0, 0, 1);//由远到近了呢

我们这样写是固定了摄像机观察的点是QVector3D(0, 0, 0),可是有个问题是不是当我们设置eye为

cameraPos = QVector3D(0, 0, 30);的时候,运行出来显示出来的效果是由远到近,然后又近到远了呢?为什么?因为

cameraPos -= cameraSpeed * QVector3D(0, 0, 1);这个值减少到负方向了?

所以我们修改下程序,修改center(摄像机观察的点)让观察点随着摄像机变化,是不是就没有由远到近 ,然后又由近到远呢?上代码


#include "glwidget.h"
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QMouseEvent>
#include <QDateTime>
#include <QtMath>

static const char *vertexShaderSource =
    "#version 330\n"
    "layout (location = 0) in vec4 vertex;\n"
    "layout (location = 1) in vec4 texCoord;\n"
    "out vec4 texc;\n"
    "uniform  mat4 matrix;\n"
    "uniform  mat4 model;\n"
    "uniform  mat4 view;\n"
    "uniform  mat4 projection;\n"
    "void main(void)\n"
    "{\n"
    "    gl_Position =  projection*view* matrix * vertex;\n"
    "    texc = texCoord;\n"
    "}\n";

static const char *fragmentShaderSource =
      "#version 330\n"
      "uniform sampler2D texture;\n"
      "in vec4 texc;\n"
      "void main(void)\n"
      "{\n"
      "    gl_FragColor = texture2D(texture, texc.st);\n"
      "}\n";

GLWidget::GLWidget():QOpenGLWidget()
  ,m_xRos(0)
  ,m_yRos(0)
{
    cam = QVector3D(m_xRos, m_yRos, m_zRos);

    cameraPos = QVector3D(0, 0, 3);

    timer = new QTimer;
    timer->setInterval(20);
    connect(timer,&QTimer::timeout,this,[=]{
        qDebug()<<"timeout"<<nCount<<m_xRos;

       rotateBy(2 * 16, +2 * 16, -1 * 16);
    });

}
GLWidget::~GLWidget()
{
    makeCurrent();
    vbo.destroy();
    for (int i = 0; i < 6; ++i)
        delete textures[i];
    delete program;
    doneCurrent();
}

QSize GLWidget::minimumSizeHint() const
{
    return QSize(400, 400);
}

QSize GLWidget::sizeHint() const
{
    return QSize(400, 400);
}

void GLWidget::rotateBy(int xAngle, int yAngle, int zAngle)
{
    float cameraSpeed = 0.2;
    cameraPos -= cameraSpeed * QVector3D(0, 0, -1);//由远到近
    //cameraPos += cameraSpeed * QVector3D(0, 0, -1);//由近到远

    xRot += xAngle;
    yRot += yAngle;
    zRot += zAngle;
    update();
}

void GLWidget::setClearColor(const QColor &color)
{
    clearColor = color;
    update();
}

void GLWidget::initializeGL()
{
    vertices = {
            // ---- 位置----   - 纹理坐标 -      ---- 颜色 ----

        0.5f, -0.5f, -0.5f,   1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, 0.5f, -0.5f,   0.0f, 0.0f,
        0.5f, 0.5f, -0.5f,   1.0f, 0.0f,//1

        0.5f, 0.5f, -0.5f,   1.0f, 1.0f,
        -0.5f, 0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, 0.5f, 0.5f,   0.0f, 0.0f,
        0.5f, 0.5f, 0.5f,    1.0f, 0.0f,//2


        0.5f, -0.5f, 0.5f,   1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, 0.5f, -0.5f,   0.0f, 0.0f,
        0.5f, 0.5f, 0.5f,    1.0f, 0.0f,//3



        -0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         -0.5f, -0.5f, 0.5f,  0.0f, 1.0f,
         -0.5f, 0.5f, 0.5f,   0.0f, 0.0f,
        -0.5f, 0.5f, -0.5f,   1.0f, 0.0f,//4


         0.5f, -0.5f, 0.5f,   1.0f, 1.0f,
         -0.5f, -0.5f, 0.5f,  0.0f, 1.0f,
         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,//5

        -0.5f, -0.5f, 0.5f,   1.0f, 1.0f,
         0.5f, -0.5f, 0.5f,   0.0f, 1.0f,
         0.5f, 0.5f, 0.5f,    0.0f, 0.0f,
        -0.5f, 0.5f, 0.5f,    1.0f, 0.0f,

    };
    initializeOpenGLFunctions();

   // makeObject();

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

//#define PROGRAM_VERTEX_ATTRIBUTE 0
//#define PROGRAM_TEXCOORD_ATTRIBUTE 1

    program = new QOpenGLShaderProgram;
    program->addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);
    program->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);
    program->link();
    program->bind();//激活Program对象

    vbo.create();
    vbo.bind();              //绑定到当前的OpenGL上下文,
    vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));


    //初始化VAO,设置顶点数据状态(顶点,法线,纹理坐标等)
    vao.create();
    vao.bind();

    for (int j = 0; j < 6; ++j)
    {
        textures[j] = new QOpenGLTexture(QImage(QString(":/cube%1.png").arg(j + 1)).mirrored());
        textures[j]->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);
        textures[j]->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);
        textures[j]->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);
    }
    program->setAttributeBuffer(0, GL_FLOAT, 0,                  3, 5 * sizeof(float));   //设置aPos顶点属性
    program->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float),  2, 5 * sizeof(float));   //设置aColor顶点颜色
    program->enableAttributeArray(0); //使能aPos顶点属性
    program->enableAttributeArray(1); //使能aColor顶点颜色
    program->setUniformValue("texture", 0);
    QMatrix4x4 projection;
    projection.perspective(60,(float)width()/height(),0.1,100);//构建透视矩阵,这个可以是固定写法
    program->setUniformValue("projection", projection);

//    vao.release();
//    vbo.release();
}

void GLWidget::paintGL()
{
    //glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.1f,0.5f,0.7f,1.0f);  //设置清屏颜色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 m;
    //m.ortho(-0.5f, +0.5f, +0.5f, -0.5f, 4.0f, 15.0f);
    m.translate(0.0f, 0.0f, 0.0f);
    m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);
    m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);
    m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);
    m.scale(0.5);
    program->setUniformValue("matrix", m);

//    QMatrix4x4 view;
//    view.translate(0.0f,0.0f,-3.0f);
//    program->setUniformValue("view", view);


    QMatrix4x4 view;
    view.lookAt(cameraPos, cameraPos+QVector3D(0,0,-1), QVector3D(0,1,0));
    program->setUniformValue("view", view);

    for (int i = 0; i < 6; ++i) {
        textures[i]->bind();
        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
    }
}
void GLWidget::resizeGL(int width, int height)
{
    this->glViewport(0,0,width,height);                //定义视口区域
}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
    timer->start();
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();

    if (event->buttons() & Qt::LeftButton) {
        rotateBy(8 * dy, 8 * dx, 0);
    } else if (event->buttons() & Qt::RightButton) {
        rotateBy(8 * dy, 0, 8 * dx);
    }
    lastPos = event->pos();
}

void GLWidget::mouseReleaseEvent(QMouseEvent * /* event */)
{
    emit clicked();
}

我们运行程序,最后点击下屏幕,是不是实现了呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ASCB1系列APP操控末端回路智能微断 物联网断路器 远程控制开关 学校、工厂、农场、商业大楼等可用

安科瑞戴婷 Acrel-Fanny ASCB1系列智能微型断路器是安科瑞电气股份有限公司全新推出的智慧用电产品&#xff0c;产品由智能微型断路器与智能网关两部分组成&#xff0c;可用于对用电线路的关键电气因素&#xff0c;如电压、电流、功率、温度、漏电、能耗等进行实时监测&#x…

JMeter监听器与压测监控之 InfluxDB

1. 简介 在本文中&#xff0c;我们将介绍如何在 Kali Linux 上通过 Docker 安装 InfluxDB&#xff0c;并使用 JMeter 对其进行性能监控。InfluxDB 是一个高性能的时序数据库&#xff0c;而 JMeter 是一个开源的性能测试工具&#xff0c;可以用于对各种服务进行负载测试和性能监…

[安洵杯 2019]iamthinking-parse_url绕过thinkphp6.0反序列化

/www.zip下载源码 查看序列化点&#xff0c;index.php <?php namespace app\controller; use app\BaseController;class Index extends BaseController {public function index(){echo "<img src../test.jpg"."/>";$paylaod $_GET[payload];i…

解决CondaError: argument COMMAND: invalid choice: ‘activate‘

自上篇系统重装后&#xff0c;Anaconda重新导入后终端进入conda环境报错&#xff1a; conda-script.py: error: argument COMMAND: invalid choice: ‘activate’ C:\Windows\system32>conda activate xin usage: conda-script.py [-h] [--no-plugins] [-V] COMMAND ... …

【CSS3】Flex弹性布局

文章目录 前言一、基本概念1.容器和项目&#xff1a;2.主轴和交叉轴&#xff1a; 二、容器属性1.flex-direction&#xff1a;决定主轴的方向&#xff0c;即x轴还是y轴2.flex-wrap&#xff1a;定义项目的换行方式3.flex-flow&#xff1a;flex-direction属性和flex-wrap属性的简写…

简述C++map容器

pair键值对 std::pair在很多关联容器&#xff08;如std::map、std::multimap、std::set、std&#xff1a;multiset等&#xff09;中被广泛应用。以std::map为例&#xff0c;std::map是一个键值对的容器&#xff0c;其中每个元素都是一个std::pair&#xff0c;键用于唯一标识元…

刷题计划 day22回溯(一)【组合】【组合总和 III】【电话号码的字母组合】

⚡刷题计划day22 回溯&#xff08;一&#xff09;开始&#xff0c;此期开启回溯专题&#xff0c;敬请期待关注&#xff0c;可以点个免费的赞哦~ 往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 回溯算法理论基础 回溯法解决的…

Qt桌面应用开发 第六天(鼠标事件 定时器事件 定时器类 事件分发器 事件过滤器)

目录 1.1鼠标进入和离开enterEvent\leaveEvent 1.2鼠标按下释放和移动mousePressEvent\mouseReleaseEvent\mouseMoveEvent 1.3定时器事件timerEvent 1.4定时器类QTimer 1.5事件分发器event 1.6事件过滤器eventFilter 1.1鼠标进入和离开enterEvent\leaveEvent 事件&#x…

【Linux清空显存占用】Linux 系统中清理 GPU 显存

操作指令 # 查看NVIDIA GPU状态和进程 nvidia-smi # 查找所有包含"python"的进程 ps -ef | grep python # 强制结束进程号为3023的进程 kill -9 3023截图演示 在 Linux 系统中清理 GPU 显存可以采用以下方法&#xff1a; 1. 终止特定进程&#xff08;常用方法&…

对撞双指针(七)三数之和

15. 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组…

vue2-基础核心

vue简介 动态构建用户界面的渐进式 JavaScript 框架 vue的特点: 遵循MVVM模式 采用组件化模式&#xff0c;提高代码复用率&#xff0c;让代码更好维护 声明式编码&#xff0c;无需直接操作DOM&#xff0c;提高开发效率&#xff0c;编码简洁、体积小&#xff0c;运行效率高 本…

Prompting LLMs to Solve Complex Tasks: A Review

文章目录 题目简介任务分解未来方向结论 题目 促使 LLM 解决复杂任务&#xff1a; 综述 论文地址&#xff1a;https://www.intjit.org/cms/journal/volume/29/1/291_3.pdf 简介 大型语言模型 (LLM) 的最新趋势显而易见&#xff0c;这体现在大型科技公司的投资以及媒体和在线社…

反射、依赖注入

特性和依赖注入都是基于反射的&#xff0c;同时反射一般和接口配合着使用。 接口隔离原则 接口隔离原则&#xff1a;主张应该把客户端对一个类的需求分解成更小、更具体的接口&#xff0c;而不是提供一个包含所有功能的大接口。 接口中的需求是&#xff1a;乙方不能少给&am…

MT8768/MTK8768安卓核心板性能参数_联发科安卓智能模块开发方案

MT8768安卓核心板 是一款采用台积电12nm FinFET制程工艺的智能手机芯片。MT8768核心板不仅提供所有高级功能和出色体验&#xff0c;同时确保智能终端具备长电池寿命。该芯片提供了一个1600x720高清(20:9比例)分辨率显示屏&#xff0c;排除了清晰度和功耗之间的平衡问题。该芯片…

VBA技术资料MF229:以毫米为单位设置行高和列宽

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

深入JMeter核心引擎:揭秘JmeterEngine、StandardJmeterEngine、ClientJmeterEngine与Remote的奥秘

引言 Apache JMeter是一款广泛使用的开源性能测试工具&#xff0c;它能够帮助开发者和测试人员模拟大量并发用户对应用程序进行负载测试。JMeter的强大功能和灵活性源于其精心设计的核心引擎。本文将深入探讨JMeter的核心引擎&#xff0c;包括JmeterEngine、StandardJmeterEng…

软件工程导论 选填题知识点总结

一 原型化方法是一种动态定义需求的方法&#xff0c;提供完整定义的需求不是原型化方法的特征&#xff0c;其特征包括尽快建立初步需求、简化项目管理以及加强用户参与和决策。 软件危机的表现包括用户对已完成的软件系统不满意的现象经常发生、软件产品的质量往往靠不住、软件…

Rust中Tracing 应用指南

欢迎来到这篇全面的Rust跟踪入门指南。Rust 的tracing是一个用于应用程序级别的诊断和调试的库。它提供了一种结构化的、异步感知的方式来记录日志和跟踪事件。与传统的日志记录相比&#xff0c;tracing能够更好地处理复杂的异步系统和分布式系统中的事件跟踪&#xff0c;帮助开…

机器学习实战:银行客户是否认购定期存款

项目结构与步骤 1. 项目概述 项目名称&#xff1a;葡萄牙银行电话营销活动分析与定期存款认购预测目标&#xff1a;通过分析银行的电话营销数据&#xff0c;构建模型预测客户是否会认购定期存款。数据来源&#xff1a;葡萄牙银行营销活动数据集关键挑战&#xff1a;数据不平衡…

服务器数据恢复—raid5阵列热备盘上线失败导致EXT3文件系统不可用的数据恢复案例

服务器数据恢复环境&#xff1a; 两组分别由4块SAS硬盘组建的raid5阵列&#xff0c;两组阵列划分的LUN组成LVM架构&#xff0c;格式化为EXT3文件系统。 服务器故障&#xff1a; 一组raid5阵列中的一块硬盘离线。热备盘自动上线替换离线硬盘&#xff0c;但在热备盘上线同步数据…