Qt实现简单的漫游器

news2024/9/25 19:14:47

文章目录

  • Qt的OpenGL窗口
  • GLSL的实现
  • 摄像机类的实现
  • 简单的漫游器

Qt的OpenGL窗口

 Qt主要是使用QOpenGLWidget来实现opengl的功能。
 QOpenGLWidget 提供了三个便捷的虚函数,可以重载,用来重新实现典型的OpenGL任务:

  • paintGL:渲染OpenGL场景。widget 需要更新时调用。
  • resizeGL:设置OpenGL视口、投影等。widget 调整大小(或首次显示)时调用。
  • initializeGL:设置OpenGL资源和状态。第一次调用 resizeGL() / paintGL() 之前调用一次。
  • 如果需要从paintGL()以外的位置触发重新绘制(典型示例是使用计时器设置场景动画),则应调用widget的update()函数来安排更新。
  • 调用paintGL()、resizeGL()或initializeGL()时,widget 的OpenGL呈现上下文将变为当前。如果需要从其他位置(例如,在 widget 的构造函数或自己的绘制函数中)调用标准OpenGL API函数,则必须首先调用makeCurrent()。
  • QOpenGLFunctions_X_X_Core 提供OpenGL X.X版本核心模式的所有功能。是对OpenGL函数的封装:
  • initializeOpenGLFunctions:初始化OpenGL函数,将Qt里的函数指针指向显卡的函数。
#include <QOpenGLWidget> 
#include <QOpenGLFunctions_3_3_Core> class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core 
{ 
Q_OBJECT 
public: 
explicit MyOpenGLWidget (QWidget *parent = nullptr); 
protected: 
virtual void initializeGL(); 
virtual void resizeGL(int w, int h); 
virtual void paintGL(); 
};
void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
}
void MyOpenGLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}
void MyOpenGLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

在这里插入图片描述

以上是最简单的实现版本。

GLSL的实现

 由于是最简单的漫游器,所以我们实现的版本只需要一个顶点着色器和一个片段着色器即可。
shapes.vert

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;

out vec2 texCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;


void main(){
    gl_Position = projection * view * model * vec4(aPos, 1.0f);
    texCoord = aTexCoord;
}

shapes.frag

#version 330 core
out vec4 FragColor;
in vec2 texCoord;

uniform sampler2D texturewall;
uniform sampler2D texturesmile;
uniform sampler2D textureSmall;

uniform float ratio;
void main(){
    FragColor = mix(texture(texturewall,texCoord),texture(texturesmile,texCoord),ratio);
}

摄像机类的实现

 这边实现了一个可以对模型进行上下左右移动,移动视角,放大缩小的操作。
摄像机类初始化了几个变量

// 默认值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;

偏航角默认为90度,灵敏度主要用于控制鼠标移动时视角的变化量。

#ifndef CAMERA_H
#define CAMERA_H


#include<QMatrix4x4>

#include <vector>

// 移动方向枚举量. 是一种抽象,以避开特定于窗口系统的输入方法
// 我们这里是WSAD
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT
};

// 默认值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;


// 一个抽象的camera类,用于处理输入并计算相应的Euler角度、向量和矩阵,以便在OpenGL中使用
class Camera
{
public:
    // camera Attributes
    QVector3D Position;
    QVector3D Front;
    QVector3D Up;
    QVector3D Right;
    QVector3D WorldUp;
    // euler Angles
    float Yaw;
    float Pitch;
    // camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // constructor with vectors
    Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // constructor with scalar values
    Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = QVector3D(posX, posY, posZ);
        WorldUp = QVector3D(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // returns the view matrix calculated using Euler Angles and the LookAt Matrix
    QMatrix4x4 GetViewMatrix()
    {
        QMatrix4x4 theMatrix;
        theMatrix.lookAt(Position, Position + Front, Up);
        return theMatrix;
    }

    // 处理从任何类似键盘的输入系统接收的输入。接受摄像机定义枚举形式的输入参数(从窗口系统中提取)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
    }

    // 处理从鼠标输入系统接收的输入。需要x和y方向上的偏移值。
    void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true)
    {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw   += xoffset;
        Pitch += yoffset;

        // 确保当投球超出边界时,屏幕不会翻转
        if (constrainPitch)
        {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // 使用更新的Euler角度更新前、右和上矢量
        updateCameraVectors();
    }

    // 处理从鼠标滚轮事件接收的输入。仅需要在垂直车轮轴上输入
    void ProcessMouseScroll(float yoffset)
    {
        Zoom -= (float)yoffset;
        if (Zoom < 1.0f)
            Zoom = 1.0f;
        if (Zoom > 75.0f)
            Zoom = 75.0f;
    }

private:
    // 根据相机的(更新的)Euler角度计算前矢量
    void updateCameraVectors()
    {
        // calculate the new Front vector
        float PI=3.1415926;
        QVector3D front;
        front.setX(cos(Yaw*PI/180.0) * cos(Pitch*PI/180.0));
        front.setY( sin(Pitch*PI/180.0));
        front.setZ(sin(Yaw*PI/180.0) * cos(Pitch*PI/180.0));
        front.normalize();
        Front = front;
        // also re-calculate the Right and Up vector
        Right = QVector3D::crossProduct(Front, WorldUp);
        // 标准化向量,因为向上或向下看得越多,向量的长度就越接近0,这会导致移动速度变慢。
        Right.normalize();
        Up    = QVector3D::crossProduct(Right, Front);
        Up.normalize();
    }
};
#endif

简单的漫游器

 漫游器的实现主要是通过Qt的窗口事件触发后将触发产生的位置偏量给摄像机类进行计算,从摄像机类中得到视图矩阵将模型的位置进行改变。
myopenglwidget.h


#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H


#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
#include <QElapsedTimer>
#include "camera.h"

class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    enum Shape
    {
        None,
        Circle,
        Rect,
        Triangle
    };
    explicit MyOpenGLWidget(QWidget *parent = nullptr);
    ~MyOpenGLWidget();

    void DrawShape(Shape shape);
    void setWireFrameMode(bool enterWireframe);
    void onTimeout();
protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();
signals:
private:
    Shape m_shape;
    QOpenGLShaderProgram shaderProgram;
    QOpenGLTexture *textureWall;
    QOpenGLTexture *textureSmile;
    QOpenGLTexture *textureSmall;
    QTimer *m_timer;
    QElapsedTimer m_time;

    Camera m_camera;

    // QWidget interface
protected:
    void keyPressEvent(QKeyEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;
};

#endif // MYOPENGLWIDGET_H

myopenglwidget.cpp

#include "myopenglwidget.h"
#include <QImage>
#include <QKeyEvent>

float vertices[] = {
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
    0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    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, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
    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,
    -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, 1.0f,
    -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
    -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    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, 1.0f,
    0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

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

    -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
    -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};

QVector<QVector3D> cubePositions= {
    QVector3D( 0.0f, 0.0f, 0.0f),
    QVector3D( 2.0f, 5.0f, -15.0f),
    QVector3D(-1.5f, -2.2f, -2.5f),
    QVector3D(-3.8f, -2.0f, -12.3f),
    QVector3D( 2.4f, -0.4f, -3.5f),
    QVector3D(-1.7f, 3.0f, -7.5f),
    QVector3D( 1.3f, -2.0f, -2.5f),
    QVector3D( 1.5f, 2.0f, -2.5f),
    QVector3D( 1.5f, 0.2f, -1.5f),
    QVector3D(-1.3f, 1.0f, -1.5f)
};

#define TIMEOUT 100

unsigned int indices[] = { // note that we start from 0!
    0, 1, 3, // first triangle
    1, 2, 3 // second triangle
};

unsigned int VBO, VAO ,EBO;

float ratio = 0.5;
QPoint deltaPos;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
    : QOpenGLWidget{parent}
{
    setFocusPolicy(Qt::StrongFocus);
    setMouseTracking(true);

    m_timer = new QTimer(this);
    connect(m_timer,&QTimer::timeout,this,&MyOpenGLWidget::onTimeout);
    m_timer->start(TIMEOUT);
    m_time.start();

    m_camera.Position = QVector3D(0.0,0.0,3.0);
}

MyOpenGLWidget::~MyOpenGLWidget()
{
    if(!isValid()) return;
    makeCurrent();
    glDeleteBuffers(1,&VBO);
    glDeleteBuffers(1,&EBO);
    glDeleteVertexArrays(1,&VAO);
    doneCurrent();
}

void MyOpenGLWidget::DrawShape(Shape shape)
{
    m_shape=shape;
    update();
}

void MyOpenGLWidget::setWireFrameMode(bool enterWireframe)
{
    makeCurrent();
    if(enterWireframe)
        glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    else
        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    update();
    doneCurrent();
}

void MyOpenGLWidget::onTimeout()
{
    update();
}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    //创建VBO和VAO对象,并赋予ID
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);

    //绑定VAO和VBO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)0);
    //开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)(3*sizeof(float)));
    //开启VAO管理的第三个属性值
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER,0);

    bool success;
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":Shaders/shapes.vert");
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":Shaders/shapes.frag");
    success = shaderProgram.link();
    if(!success)
    {
        qDebug()<<"Error:"<<shaderProgram.log();
    }

    shaderProgram.bind();
    shaderProgram.setUniformValue("ratio",ratio);
    shaderProgram.setUniformValue("texturewall",0);
    shaderProgram.setUniformValue("texturesmile",1);
    shaderProgram.setUniformValue("textureSmall",2);

    unsigned int EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    textureWall = new QOpenGLTexture(QImage(":Images/images/wall.jpg").mirrored());
    textureSmile = new QOpenGLTexture(QImage(":Images/images/awesomeface.png").mirrored());
    textureSmall = new QOpenGLTexture(QImage(":Images/images/small.png").mirrored());
    glBindVertexArray(0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}

void MyOpenGLWidget::paintGL()
{
    QMatrix4x4 model;
    QMatrix4x4 view;
    QMatrix4x4 projection;

    view=m_camera.GetViewMatrix();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderProgram.bind();
    projection.perspective(m_camera.Zoom,(float)width()/(height()),0.1,100.0);
    shaderProgram.setUniformValue("projection", projection);
    shaderProgram.setUniformValue("view", view);

    glBindVertexArray(VAO);
    //glDrawArrays(GL_TRIANGLES, 0, 3);
    switch(m_shape)
    {
    case Rect:
        textureWall->bind(0);
        textureSmile->bind(1);
        textureSmall->bind(2);

        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


        foreach (auto item, cubePositions)
        {
            model.setToIdentity();
            model.translate(item);

            shaderProgram.setUniformValue("model", model);
            glDrawArrays(GL_TRIANGLES,0,36);
        }
        break;
    case None:
        break;
    case Triangle:
        break;
    case Circle:
        break;
    }

}

void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{
    float deltatime=TIMEOUT / 1000.0;
    switch(event->key())
    {
    case Qt::Key_Up:ratio += 0.1;break;
    case Qt::Key_Down:ratio -= 0.1;break;
    case Qt::Key_W: m_camera.ProcessKeyboard(FORWARD,deltatime);break;
    case Qt::Key_S: m_camera.ProcessKeyboard(BACKWARD,deltatime);break;
    case Qt::Key_D: m_camera.ProcessKeyboard(RIGHT,deltatime);break;
    case Qt::Key_A: m_camera.ProcessKeyboard(LEFT,deltatime);break;
    }

    if(ratio > 1) ratio = 1;
    if(ratio < 0) ratio = 0;

    makeCurrent();
    shaderProgram.bind();
    shaderProgram.setUniformValue("ratio",ratio);
    update();
    doneCurrent();
}

void MyOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    static QPoint lastPos(width()/2,height()/2);
    auto currentPos=event->pos();
    deltaPos=currentPos-lastPos;
    lastPos=currentPos;

    m_camera.ProcessMouseMovement(deltaPos.x(),-deltaPos.y());
    update();
}

void MyOpenGLWidget::wheelEvent(QWheelEvent *event)
{   
    m_camera.ProcessMouseScroll(event->angleDelta().y()/120);
    update();
}

完整代码链接

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

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

相关文章

零基础入门网络安全,收藏这篇不迷茫【2023最新】

前言 最近收到不少关注朋友的私信和留言&#xff0c;大多数都是零基础小友入门网络安全&#xff0c;需要相关资源学习。其实看过的铁粉都知道&#xff0c;之前的文里是有过推荐过的。新来的小友可能不太清楚&#xff0c;这里就系统地叙述一遍。 01.简单了解一下网络安全 说白…

【ARM Linux 系统稳定性分析入门及渐进12 -- GDB内存查看命令 “x“(examine)】

文章目录 gdb 内存查看命令 examine 上篇文章&#xff1a;ARM Linux 系统稳定性分析入门及渐进11 – GDB( print 和 p 的使用| 和 &#xff1a;&#xff1a;的使用|ptype|{&#xff1c;type&#xff1e;} &#xff1c;addr&#xff1e; ) gdb 内存查看命令 examine examine是…

【C# 基础精讲】LINQ 基础

LINQ&#xff08;Language Integrated Query&#xff09;是一项强大的C#语言特性&#xff0c;它使数据查询和操作变得更加简洁、灵活和可读性强。通过使用LINQ&#xff0c;您可以使用类似SQL的语法来查询各种数据源&#xff0c;如集合、数组、数据库等。本文将介绍LINQ的基础概…

Kvm配置ovs网桥

环境&#xff1a;部署在kvm虚拟环境上&#xff08;让虚拟机和宿主机都可以直接从路由器获取到独立ip&#xff09; 1、安装ovs软件安装包并启动服务&#xff08;一般采用源码安装&#xff0c;此处用yum安装&#xff09; yum install openvswitch-2.9.0-3.el7.x86_64.rpm syste…

UVC摄像头

1 版本历史 1.1 UVC uvc_version UVC 1.0: Sep-4-2003 UVC 1.1: Jun-1-2005 UVC 1.5: August-9-2012, H.264 video codec. Linux 4.5 introduces UVC 1.5, but does not support H264. 1.2 V4L版本历史 Video4Linux取名的灵感来自1992 Video for Windows&#xff08;V4W&#x…

第一节 Dubbo框架的介绍

1. 什么是Dubbo &#xff1f; 官⽹地址&#xff1a; http://dubbo.apache.org/zh/ ⽬前&#xff0c;官⽹上是这么介绍的&#xff1a;Apache Dubbo 是⼀款⾼性能、轻量级的开源 Java 服务 框架 在⼏个⽉前&#xff0c;官⽹的介绍是&#xff1a;Apache Dubbo 是⼀款⾼性能、轻…

mysql的两张表left join 进行关联后,索引进行优化案例

一 mysql的案例 1.1 不加索引情况 1.表1没加索引 2.表2没加索引 3.查看索引 1.2 添加索引 1.表1添加索引 2.表2添加索引 3.查看

python使用dir()函数获取对象中可用的属性和方法(看不到python源码又想知道怎么调用,DLL调用分析,SDK二次开发技巧)

有时候调用一些SDK&#xff0c;但是人家又是封装成dll文件形式调用的&#xff0c;这时没法看源码&#xff0c;也不想看其对应的开发文档&#xff08;尤其有些开发文档写得还很难懂&#xff0c;或者你从某个开源社区拿过来&#xff0c;就根本没找到开发文档&#xff09;&#xf…

回归预测 | MATLAB实现IPSO-SVM改进粒子群优化算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现IPSO-SVM改进粒子群优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现IPSO-SVM改进粒子群优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xf…

回归预测 | MATLAB实现WOA-BP鲸鱼优化算法优化BP神经网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现WOA-BP鲸鱼优化算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现WOA-BP鲸鱼优化算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本…

运动恢复结构(SfM)_OpenMVG_代码的核心逻辑

参考: 深蓝学院,基于图像的三维重建 课程 1. 输入输出 数据集 fountain,选⾃Lund University开源的三维重建数据集 (http://www.maths.lth.se/matematiklth/personal/calle/dataset/dataset.html ) 2. 特征提取与特征匹配

优于立方复杂度的 Rust 中矩阵乘法

优于立方复杂度的 Rust 中矩阵乘法 迈克克维特 跟随 发表于 更好的编程 6 分钟阅读 7月 <> 143 中途&#xff1a;三次矩阵乘法 一、说明 几年前&#xff0c;我在 C 年编写了 Strassen 矩阵乘法算法的实现&#xff0c;最近在 Rust 中重新实现了它&#xff0c;因为我继续…

TCP报文段的首部格式

TCP传送的数据单元称为报文段&#xff0c;既可以用来运载数据&#xff0c;又可以用来建立连接、释放连接和应答 一个TCP报文段可以分为首部和数据部分&#xff0c;整个TCP报文段作为IP数据报的数据部分封装在IP数据报中。首部的固定长度为20B&#xff0c;因此最短为20B&#xf…

17-工程化开发 脚手架 Vue CLI

开发Vue的两种方式: 1.核心包传统开发模式: 基于 html/css /js 文件&#xff0c;直接引入核心包&#xff0c;开发 Vue。 2.工程化开发模式: 基于构建工具 (例如: webpack)的环境中开发 Vue。 问题: 1. webpack 配置不简单 2. 雷同的基础配置 3. 缺乏统…

2023.8 - java - 对象和类

public class Dog {String breed;int size;String colour;int age;void eat() {}void run() {}void sleep(){}void name(){} } 一个类可以包含以下类型变量&#xff1a; 局部变量&#xff1a;在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方…

01-关于new Object()的问题

美团面试题关于Object o = new Object()的几个问题。 1、对象在内存中的存储布局? 实例化一个对象,在堆区开辟一段空间。 堆区由markword、类型指针(class point)、实例数据、对齐组成。 markword:由8个字节组成。 类型指针(class point):就是指向某class文件的指针,…

外网连接局域网的几种方式?快解析内网穿透安全便利吗?

外网连接局域网是一项网络连接中的关键技术&#xff0c;它能够让远程用户通过互联网访问内部局域网中的资源和服务。外网连接局域网为企业提供了更大的灵活性和便捷性&#xff0c;但也需要严格的安全措施来防止未经授权的访问。 外网连接局域网的几种方式 在将外网连接到局域…

数组详解

1. 一维数组的创建和初始化 1.1 数组的创建 数组是一组相同类型元素的集合。 数组的创建方式&#xff1a; type_t arr_name [const_n]; //type_t 是指数组的元素类型 //const_n 是一个常量表达式&#xff0c;用来指定数组的大小 数组创建的实例&#xff1a; //代码1 int a…

SpringMVC之入门搭建框架

文章目录 前言一、SpringMVC简介1.什么是MVC2.什么是SpringMVC3.SpringMVC的特点 二、搭建框架——HelloWorld1.创建maven工程&#xff08;web项目&#xff09;2.配置web.xml3.配置springMVC.xml4.创建请求控制器 总结 前言 基础小白第一次走进SpringMVC&#xff1a;了解什么是…

@mouseover不起作用,并没有触发

我的错误代码如下&#xff1a; <el-rowv-for"version in item.version_list":key"version.id":class"{ blue-background: versionItem.id version.id }"mouseover.native"version.isHovered true"mouseleave.native"version…