当前位置: 首页 > news >正文

基于QT使用OpenGL,加载obj模型,进行鼠标交互

目录

  • 功能分析(需求分析)
  • 技术点分析
    • OpenGL
      • 立即渲染模式
      • 可编程渲染管线模式
    • QOpenGLWidget
      • 派生类 glwidget逻辑
        • glwidget.h
        • glwidget.cpp
    • 鼠标交互功能
    • obj格式介绍
  • 效果
    • bunny
    • Cayman_GT

功能分析(需求分析)

  1. 基于QT平台,使用OpenGL进行obj文件加载显示;
  2. 使用鼠标对场景进行缩放、移动、旋转交互;

技术点分析

OpenGL

  OpenGL是基于C的,学习曲线比较抖,但是总的来说就是下面一幅图,
在这里插入图片描述

  用语言简单的描述(个人理解,可能不太准确)是把cpu里内存里的3D数据,传输到显卡的内存里,以及如何转换成2D平面上像素点显示(也就是矩阵变换,在好多开源的框架里都进行了进一步封装,形成了渲染器、场景、相机等)。这个数据是顶点坐标、颜色等,传输跟送快递一样,除了要有数据本身之外,还要有其他信息,也就是要有个约定,到显卡拿到数据之后怎么解析。
  有个网站比较有名learnopengl,可以对着学一遍,在网上找资料的时候,需要注意是立即渲染模式,还是可编程渲染管线模式,现在官方推荐是使用可编程渲染管线模式开发。

立即渲染模式

glBegin(GL_TRIANGLES)
glTranslatef(1,2,3);
// 其他操作
// glVertex*() 设置顶点坐标
// glColor*() 设置当前颜色
// glIndex*() 设置当前颜色表
// glNormal*() 设置法向坐标
// glEvalCoord*() 产生坐标
// glTexCoord*() 设置纹理坐标
// glEdgeFlag*() 控制边界绘制
// glMaterial*() 设置材质
glEnd()

可编程渲染管线模式

1、创建VBO顶点数据对象GLuint VBO;glGenBuffers(1,&VBO);
2、VBO与显卡缓存绑定glBindBuffer(GL_ARRAY_BUFFER, VBO)
3、绑定数据缓存对象glBufferData(GL_ARRAY_BUFFER,sizeof(vertexs),vertex,)
4、数据格式glVertexAttribPoint(0,3,GL_FLOAT,)
5、启用/绘制glEnableVertexAttribArray(0)glDrawArrays(GL_TRIANGLES, 0, 10);
6、最后关闭glBindBuffer(GL_ARRAY_BUFFER,0)glBindVertexArray(0);

  以上两段代码只是展示两种模式区别,很明显立即渲染模式容易理解,但是性能有限制,可编程渲染管线模式理解和使用门槛高,但更能接触底层。

QOpenGLWidget

  QT对OpenGL进行了封装,提供了QOpenGLWidget类,只需要对其继承,在initialzeGL()resizeGL()paintGL()逻辑下进行业务实现,包括VBO、VAO的创建与绑定,着色器程序的编译与链接等。

派生类 glwidget逻辑

  先简单介绍派生类的写法,当然为了方便扩展和使用,抽象出了相机类、渲染器类、物体类,完整的工程代码资源可以下载参考,具体的可以根据自己要实现的功能进行编写。

glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QMouseEvent>
#include <QTimer>
#include <QQuaternion>#include <vector>
#include <QKeyEvent>#include "utils/Common.h"
#include "genericRender.h"
#include "grid.h"
#include "coorsystem.h"
#include "camera.h"class glwidget :public QOpenGLWidget, QOpenGLFunctions_3_3_Core
{Q_OBJECT
public:glwidget(QWidget * parent = nullptr);//鼠标交互事件重写void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void wheelEvent(QWheelEvent *event) override;//键盘交互void keyReleaseEvent(QKeyEvent *event) override; //按键释放事件void keyPressEvent(QKeyEvent *event) override;   //按键按下事件void slotTimeOut();
protected:virtual void initializeGL();virtual void resizeGL(int w, int h);virtual void paintGL();
public:GenericRender m_render;//渲染器Camera m_camera;//相机grid m_grid;//网格平面xycoorSystem m_coordsys;//坐标系QTimer tm_;
public:QList<int> keys;QTimer* keyRespondTimer;	//头文件中添加成员static int mouse_button;static int modifier_key;
public://鼠标变量static double mouse_pos_x_old;static double mouse_pos_y_old;bool changeview_ = false;            //改变视角的标志位float fov = 2.0f;          //视野范围
};
#endif // GLWIDGET_H
glwidget.cpp
#include "glwidget.h"
#include "box.h"
int glwidget::mouse_button = -1;
int glwidget::modifier_key = 0;
double glwidget::mouse_pos_x_old = 0;
double glwidget::mouse_pos_y_old = 0;
glwidget::glwidget(QWidget * parent):QOpenGLWidget(parent)
{keyRespondTimer = new QTimer(this);	//构造函数中创建定时器对象,并连接信号槽connect(keyRespondTimer, &QTimer::timeout, this, &glwidget::slotTimeOut);setFocusPolicy(Qt::StrongFocus);//否则进入不了键盘事件监听
}void glwidget::initializeGL()
{initializeOpenGLFunctions();glEnable(GL_DEPTH_TEST);m_render.init();m_camera.setMatPro(fov);QStringList renderfiles={":/obj/data/Cayman_GT.obj", ":/obj/data/bunny_10k.obj"};for(QString file : renderfiles){Box* b1 = new Box();b1->load(file);m_render.addBox(b1);}m_grid.initize();m_coordsys.initize();
}void glwidget::resizeGL(int w, int h)
{m_camera.setRatio((float)width() / (float)height());
}void glwidget::paintGL()
{glClearColor(1.0f, 1.0f, 1.0f, 0.1f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPolygonMode(GL_FRONT, GL_LINE);QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();QMatrix4x4 mMatrix;m_camera.setMatPro(fov);m_grid.paint(f,m_camera.getMatPro(),m_camera.getMatView(),mMatrix);m_coordsys.paint(f,m_camera.getMatPro(),m_camera.getMatView(),mMatrix);m_render.render(f,m_camera,mMatrix);
}void glwidget::mousePressEvent(QMouseEvent *event){mouse_pos_x_old = event->pos().x();mouse_pos_y_old = event->pos().y();mouse_button = event->button();
}void glwidget::mouseMoveEvent(QMouseEvent *event){int x = event->pos().x();int y = event->pos().y();double w = width(), h = height();double d_x = (mouse_pos_x_old - x)/w;double d_y = (mouse_pos_y_old - y)/h;if (mouse_button == Qt::LeftButton){foreach (int key, keys) {switch (key) {case Qt::Key_Control:m_camera.rotateY(-d_x*180*5);m_camera.rotateX(-d_y*180*5);break;case Qt::Key_Shift:m_camera.move(5*d_x, 5*d_y, 0);break;default:break;}}}mouse_pos_x_old = x;mouse_pos_y_old = y;this->repaint();
}void glwidget::mouseReleaseEvent(QMouseEvent *event){  //鼠标左键松开禁止改变相机视角changeview_ = false;
}void glwidget::wheelEvent(QWheelEvent *event){if (event->delta() > 0)fov-=2.0f;elsefov+=2.0f;if (fov<0.50f)fov = 0.5f;if (fov>=200.f)fov = 200.0;this->repaint();
}void glwidget::keyReleaseEvent(QKeyEvent *event)
{if(!event->isAutoRepeat())  //判断如果不是长按时自动触发的释放,就将key值从容器中删除keys.removeAll(event->key());if(keys.isEmpty()) //容器空了,关闭定时器keyRespondTimer->stop();
}void glwidget::keyPressEvent(QKeyEvent *event)
{if(!event->isAutoRepeat())  //判断如果不是长按时自动触发的按下,就将key值加入容器keys.append(event->key());if(!keyRespondTimer->isActive()) //如果定时器不在运行,就启动一下keyRespondTimer->start(4);
}void glwidget::slotTimeOut(){foreach (int key, keys) {switch (key) {case Qt::Key_D:break;case Qt::Key_Shift:modifier_key = Qt::Key_Shift;break;default:break;}}
}

鼠标交互功能

  交互的功能实现是重载QOpenGLWidget的鼠标事件函数,修改相应的矩阵,也就对应最上面的相机变化、灯光变化等;

obj格式介绍

  OBJ文件(.obj)包含有关3D对象的几何体的信息,下面是一个长方体的obj格式文件;

#
# Object file
#
mtllib Cube3x3x10.mtl
# Cube3x3x10\实体
v 0 0 0
v 3.00000002607703 0 0
v 3.00000002607703 0 9.99999977648258
v 0 0 9.99999977648258
v 3.00000002607703 3.00000002607703 9.99999977648258
v 0 3.00000002607703 9.99999977648258
v 0 0 9.99999977648258
v 3.00000002607703 0 9.99999977648258
v 0 3.00000002607703 9.99999977648258
v 0 3.00000002607703 0
v 0 0 0
v 0 0 9.99999977648258
v 0 3.00000002607703 0
v 3.00000002607703 3.00000002607703 0
v 3.00000002607703 0 0
v 0 0 0
v 3.00000002607703 3.00000002607703 0
v 3.00000002607703 3.00000002607703 9.99999977648258
v 3.00000002607703 0 9.99999977648258
v 3.00000002607703 0 0
v 3.00000002607703 3.00000002607703 9.99999977648258
v 3.00000002607703 3.00000002607703 0
v 0 3.00000002607703 0
v 0 3.00000002607703 9.99999977648258
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vt 0 0
vt 0 0.00300000002607703
vt 0.00999999977648258 0.00300000002607703
vt 0.00999999977648258 0
vt 0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0
vt 0.00150000001303852 0
vt 0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0
vt 0.00499999988824129 0
vt 0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0
vt 0.00150000001303852 0
vt 0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0
vt 0.00499999988824129 0
vt 0.00999999977648258 0.00300000002607703
vt 0 0.00300000002607703
vt 0 0
vt 0.00999999977648258 0
o Cube3x3x10\实体
s off
# face 0
f 2/2/2 3/3/3 1/1/1
f 1/1/1 3/3/3 4/4/4
# face 1
f 5/5/5 6/6/6 8/8/8
f 8/8/8 6/6/6 7/7/7
# face 2
f 9/9/9 10/10/10 12/12/12
f 12/12/12 10/10/10 11/11/11
# face 3
f 13/13/13 14/14/14 16/16/16
f 16/16/16 14/14/14 15/15/15
# face 4
f 17/17/17 18/18/18 20/20/20
f 20/20/20 18/18/18 19/19/19
# face 5
f 21/21/21 22/22/22 24/24/24
f 24/24/24 22/22/22 23/23/23

  其中

  • mtllib Cube3x3x10.mtl   表示引用的材质文件的文件名
  • v 0 0 0          表示一个点的xyz坐标,使用空格隔开
  • vn 0 -1 0        表示一个点的法向量,使用空格隔开
  • vt 0.09 0        表示uv纹理坐标,使用空格隔开
  • f 2/2/2 3/3/3 1/1/1    表示一个面, 2/2/2依次为顶点索引,纹理坐标索引,法向索引,因为是三角面片,所以是三组,也有超多三个点的,自己造轮子的时候要注意
  • o Cube      表示指定了模型名称为Cube
  • s off       表示关闭光滑组

void ObjLoader::load(QString filename)
{// 打开文件QFile file(filename);if(!file.open(QIODevice::ReadOnly)){qDebug()<<"[Error] fail to open file: "<< filename;return;}// 读取文件QTextStream ts(&file);// 临时存储QVector<QVector3D> v;QVector<QVector3D> vn;QVector<QVector3D> vt;QVector<QStringList> str_faces;QVector<Face> faces;while(!ts.atEnd()){QStringList list = ts.readLine().split(QRegExp("(\\s+)"));list.removeAll(" ");if(list.size() == 0 )break;if(list[0] == "v")v.push_back(QVector3D(list[1].toFloat(),list[2].toFloat(),list[3].toFloat()));if(list[0] == "vn")vn.push_back(QVector3D(list[1].toFloat(),list[2].toFloat(),list[3].toFloat()));if(list[0] == "vt")vt.push_back(QVector3D(list[1].toFloat(),list[2].toFloat(),0));if(list[0] == "f")str_faces.push_back(list);}for( int i =0; i< str_faces.size(); i++){Face face;for( int j = 1; j<=3; j++)  //obj中顶点索引是从1开始{QStringList list = str_faces[i][j].split("/");face.v[j-1] = list[0].toInt() -1;face.t[j-1] = list[1].toInt() -1;face.n[j-1] = list[2].toInt() -1;}faces.push_back(face);}for( int i = 0; i<faces.size();i++){QVector3D a,b,c,na,nb,nc;a = v[faces[i].v[0]];b = v[faces[i].v[1]];c = v[faces[i].v[2]];na = vn[faces[i].n[0]];nb = vn[faces[i].n[1]];nc = vn[faces[i].n[2]];mv.push_back(a.x());mv.push_back(a.y());mv.push_back(a.z());mv.push_back(b.x());mv.push_back(b.y());mv.push_back(b.z());mv.push_back(c.x());mv.push_back(c.y());mv.push_back(c.z());mn.push_back(na.x());mn.push_back(na.y());mn.push_back(na.z());mn.push_back(nb.x());mn.push_back(nb.y());mn.push_back(nb.z());mn.push_back(nc.x());mn.push_back(nc.y());mn.push_back(nc.z());}file.close();std::cout<< filename.toStdString() <<" id succeded!\t model_size:"<<mv.size()/3<<std::endl;
}

效果

 暂时还不会弄视频或者动态图,先看个静态效果吧

bunny

在这里插入图片描述

Cayman_GT

在这里插入图片描述

相关文章:

基于QT使用OpenGL,加载obj模型,进行鼠标交互

目录 功能分析&#xff08;需求分析&#xff09;技术点分析OpenGL立即渲染模式可编程渲染管线模式 QOpenGLWidget派生类 glwidget逻辑glwidget.hglwidget.cpp 鼠标交互功能obj格式介绍 效果bunnyCayman_GT 功能分析&#xff08;需求分析&#xff09; 基于QT平台&#xff0c;使…...

三大赛题指南发布!2023 冬季波卡黑客松本周末开启 Workshop

2023 年一众黑客松赛事中&#xff0c;为什么我们建议您选择波卡黑客松大赛&#xff1f;或许答案在于——作为开发者极度友好的技术生态&#xff0c;波卡能够从参赛者的立场出发&#xff0c;为大家提供从 0 到 1 实现项目孵化成长的机会。这里聚集了一线技术专家的资源力量&…...

数据结构与算法(Java版) | 算法的空间复杂度简介

关于算法的空间复杂度&#xff0c;下面我给大家作一个简单介绍。 类似于时间复杂度的讨论&#xff0c;一个算法的空间复杂度&#xff08;Space Complexity&#xff09;定义为该算法所耗费的存储空间&#xff0c;同样&#xff0c;它也是问题规模n的一个函数。 其实&#xff0c…...

大数据-之LibrA数据库系统告警处理(ALM-12037 NTP服务器异常)

告警解释 当NTP服务器异常时产生该告警。 当NTP服务器异常消除时&#xff0c;该告警恢复。 告警属性 告警ID 告警级别 可自动清除 12037 严重 是 告警参数 参数名称 参数含义 ServiceName 产生告警的服务名称。 RoleName 产生告警的角色名称。 HostName 异常N…...

烟草5G智慧工厂数字孪生可视化平台,赋能烟草工业数字化智慧转型

随着卷烟工厂提质增效需求增强&#xff0c;信息化建设推进及生产制造系统智能化改革发展&#xff0c;各生产单元逐步升级完善数字化&#xff0c;最终实现智能制造成为必然趋势。因此&#xff0c;5G卷烟加工工厂的数字化转型迫在眉睫。中国烟草制造行业正迈向全新的市场经济时代…...

PHP编写采集药品官方数据的程序

在 PHP 中编写爬虫程序&#xff0c;首先我们需要引入一些必要的库&#xff0c;如 curl 和 file_get_contents。然后&#xff0c;我们需要设置爬虫ip信息&#xff0c;以便我们可以从指定的爬虫ip服务器上获取数据。 // 引入必要的库 require_once curl.php;// 设置爬虫ip信息 $p…...

解决Jenkins执行git脚本时报错:No such device or address问题

问题现象&#xff1a; Jenkins执行BeanShell脚本时&#xff0c;报错&#xff1a;jenkins fatal: could not read Username for http://112.11.120.1: No such device or address 解决方案&#xff1a; 解决服务器拉取git仓库的代码权限&#xff0c;使用高级子模块克隆功能。…...

LCD英文字模库(16x8)模拟测试程序

字模 字模&#xff0c;就是把文字符号转换为LCD能识别的像素点阵信息。 电子发烧友可能都熟悉字模的用途。就是调用者通过向LCD模块发送字模数据&#xff0c;LCD根据字模数据在LCD面板上相应的像素描绘出图形或文字。 现在&#xff0c;大部分的LCD都内置了字模库&#xff0c…...

二分法

文章目录 二分法概述二分 > value最左的位置二分 < value最右的位置局部最小值问题 二分法概述 什么是二分法呢&#xff1f;相信大家都有所了解&#xff0c;举个最经典的二分的例子。 ​ 给定一个整型有序数组&#xff0c;和一个值 v a l u e value value&#xff0c;如…...

Linux文件类型与权限及其修改

后面我们写代码时&#xff0c;写完可能会出现没有执行权限什么的&#xff0c;所以我们要知道文件都有哪些权限和类型。 首先 就像我们之前目录结构图里面有个/dev,它就是存放设备文件的&#xff0c;也就是说&#xff0c;哪怕是一个硬件设备&#xff0c;例如打印机啥的&#xf…...

RPC 框架 openfeign 介绍和学习使用总结

一、基本概念 RPC 远程过程调用&#xff08;Remote Procedure Call&#xff09;的缩写形式 Birrell 和 Nelson 在 1984 发表于 ACM Transactions on Computer Systems 的论文《Implementing remote procedure calls》对 RPC 做了经典的诠释。 RPC 是指计算机 A 上的进程&am…...

大厂真题:【DP/贪心】字节跳动2023秋招-小红的 01 串

题目描述与示例 题目描述 小红拿到了一个 01 串&#xff0c;她准备将若干个字符1 染成红色&#xff0c;将若干个字符0 染成蓝色&#xff0c;但有个限制&#xff1a;如果一个0 和一个1 相邻&#xff0c;那么它们不能同时染色。 小红想知道&#xff0c;最多可以染多少个字符&a…...

【技术类-01】doc转PDF程序卡死的解决方案,

摘要&#xff1a; 1、报错&#xff1a; raise AttributeError("%s.%s" % (self._username_, attr))&#xff09; 2、表现&#xff1a;doc转PDF卡死&#xff08;白条不动或出现以上英文&#xff09; 3、解决&#xff1a;在docx保存代码行后面加上time.sleep(3) 4、…...

探索未来,开启无限可能:打造智慧应用,亚马逊云科技大语言模型助您一臂之力

文章目录 什么是大模型&#xff1f;大模型训练方法亚马逊云科技推出生成式AI新工具 —— aws toolkit使用教程 总结 什么是大模型&#xff1f; 近期&#xff0c;生成式大模型是人工智能领域的研究热点。这些生成式大模型&#xff0c;诸如文心一言、文心一格、ChatGPT、Stable …...

HTML点击链接强制触发下载

常见网页中会有很多点击链接即下载的内容&#xff0c;以下示范一下如何实现 <a href"文件地址" download"下载的文件名字&#xff08;不包括后缀&#xff09;">强制下载</a> 下面举个例子&#xff1a; <a href"./image/test.jpg"…...

Paimon 与 Spark 的集成(一)

Paimon Apache Paimon (incubating) 是一项流式数据湖存储技术&#xff0c;可以为用户提供高吞吐、低延迟的数据摄入、流式订阅以及实时查询能力。Paimon 采用开放的数据格式和技术理念&#xff0c;可以与 ApacheFlink / Spark / Trino 等诸多业界主流计算引擎进行对接&#xf…...

批量导入SQL Server中的建表、建存储过程和建调度作业的文件

要批量导入SQL Server中的建表、建存储过程和建调度作业的文件&#xff0c;可以按照以下步骤进行操作&#xff1a; 确保你拥有适当的权限&#xff1a;在导入这些文件之前&#xff0c;请确保你具有足够的权限来创建表、存储过程和调度作业。通常需要具备数据库管理员&#xff08…...

启动Hbase出现报错

报错信息&#xff1a;slave1:head: cannot open/usr/local/hbase-2.3.1/bin/../logs/hbasewanggiqi-regionserver-slavel.out’ for reading: No such file or direslave2: head: cannot open/usr/local/hbase-2.3.1/bin/../logs/hbasewangqiqi-regionserver-slave2.out’ for …...

【数据结构】——栈、队列简答题模板

目录 一、栈&#xff08;一&#xff09;栈的基本概念&#xff08;二&#xff09;栈的应用&#xff08;三&#xff09;栈的代码实现&#xff08;四&#xff09;递归算法&#xff08;五&#xff09;栈与队列的区别 二、队列&#xff08;一&#xff09;队列的基本概念&#xff08;…...

基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(排它条件网关)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 这个章节来完成并行网关与排它条件网关的功能 1、前端 目前就修改了排它条件网关的前端条件部分&#xf…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...

本地部署drawDB结合内网穿透技术实现数据库远程管控方案

文章目录 前言1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 前言 在数字化浪潮席卷全球的背景下&#xff0c;数据治理能力正日益成为构建现代企业核心竞争力的关键因素。无论是全球500强企业的数据中枢系统&#xff0c;还是初创…...