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

OpenGL —— 2.8、漫游之摄像机飞行移动(附源码,glfw+glad)

源码效果

C++源码


     纹理图片
在这里插入图片描述

     
     需下载stb_image.h这个解码图片的库,该库只有一个头文件。

在这里插入图片描述

     具体代码:

          vertexShader.glsl

#version 330 corelayout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aUV;out vec2 outUV;uniform mat4 _modelMatrix;
uniform mat4 _viewMatrix;
uniform mat4 _projMatrix;void main()
{gl_Position = _projMatrix* _viewMatrix *  _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);outUV = aUV;
}

          vertexShader.glsl

#version 330 coreout vec4 FragColor;in vec2 outUV;uniform sampler2D ourTexture;void main()
{// 使用图片纹理及色彩混合FragColor = texture(ourTexture, outUV);
}

          OpenGLClass.cpp

#include "OpenGLClass.h"void OpenGLClass::bck_GLFWframebuffersizefun(GLFWwindow* window, int width, int height)
{// 在窗口中定义一个像素矩形,最终的图形将映射到个矩形中glViewport(0, 0, width, height);
}OpenGLClass::OpenGLClass()
{// 初始化glfw上下文if (glfwInit() == GLFW_FALSE) { std::cout << "glfwInit fail!\n"; return; }glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);					// 3.3版本glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);	// 使用OpenGL核心模式// 创建OpenGL窗体GLFWwindow *window = glfwCreateWindow(windowWidth, windowHeight, "OpenGL Core", nullptr, nullptr);if (!window) { std::cout << "glfwCreateWindow fail!\n"; return; }// 当前OpenGL上下文绑定窗口glfwMakeContextCurrent(window);// 加载所有OpenGL函数指针if (GL_FALSE == gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "gladLoadGLLoader fail!\n"; return; }// 在窗口中定义一个像素矩形,最终的图形将映射到个矩形中glViewport(0, 0, windowWidth, windowHeight);// 窗口大小调整回调glfwSetFramebufferSizeCallback(window, OpenGLClass::bck_GLFWframebuffersizefun);_camera.setSpeed(0.02f);_camera.lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));// 初始化VAO/VBOinitModel();// 初始化纹理if (!initTexture()) { std::cout << "initTexture fail!\n"; system("pause"); return; }// 初始化shaderif (!initShader("vertexShader.glsl", "fragmentShader.glsl")) { std::cout << "initShader fail!\n"; system("pause"); return; }// 窗口标志是否是关闭while (!glfwWindowShouldClose(window)){// 输入按键处理ProcessKeyPInput(window);#if 0// 使用红,绿,蓝以及alpha值来清除颜色缓冲区glClearColor(0.328125f, 0.35156f, 0.82421f, 1.0f);// 将从窗口中清除最后一次所绘制的图形/*GL_COLOR_BUFFER_BIT:    当前可写的颜色缓冲GL_DEPTH_BUFFER_BIT:    深度缓冲GL_ACCUM_BUFFER_BIT:	累积缓冲GL_STENCIL_BUFFER_BIT:	模板缓冲*/glClear(GL_COLOR_BUFFER_BIT);
#endifFlushRender();// 双缓冲,使用OpenGL或OpenGL ES进行渲染glfwSwapBuffers(window);// glfw事件循环glfwPollEvents();// 睡眠10ms,防止造成GPU疯狂消耗。实际具体调整Sleep(10);}// 释放窗口glfwDestroyWindow(window);// 释放资源,终止GLFW库glfwTerminate();
}OpenGLClass::~OpenGLClass()
{// 释放if (glIsProgram(shaderProgram)) { glDeleteProgram(shaderProgram); }shaderProgram = 0;if (glIsBuffer(VAO)) { glDeleteBuffers(1, &VAO); } VAO = 0;if (glIsBuffer(VBO)) { glDeleteBuffers(1, &VBO); } VBO = 0;
}void OpenGLClass::ProcessKeyPInput(GLFWwindow *window)
{if (window){if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)		// 获取窗口按键是否ESC{// 设置窗口关闭标志glfwSetWindowShouldClose(window, true);}if (glfwGetKey(window, GLFW_KEY_LEFT_BRACKET) == GLFW_PRESS){_camera.setSpeed(_camera.getSpeed() - 0.005);std::cout << "已按'[' 减速键:速度-0.005,当前速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_RIGHT_BRACKET) == GLFW_PRESS){_camera.setSpeed(_camera.getSpeed() + 0.005);std::cout << "已按']' 增速键:速度+0.005,当前速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_FRONT);std::cout << "已按'w'键:向(前)运动,速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_BACK);std::cout << "已按's'键:向(后)运动,速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_LEFT);std::cout << "已按'a'键:向(左)运动,速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_RIGHT);std::cout << "已按'd'键:向(右)运动,速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_UP);std::cout << "已按'↑'键:向(上)运动,速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_DOWN);std::cout << "已按'↓'键:向(上)运动,速度为:" << _camera.getSpeed() << std::endl;}if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS){_camera.move(CAMERA_MOVE::MOVE_InitialPosition);std::cout << "********** 已按' ' (空格)恢复初始位置! **********" << std::endl;}}window = nullptr;
}void OpenGLClass::setMatrix(const std::string &_name, glm::mat4 _matrix) const
{// 获得指定shader程序中uniform变量的位置int shaderNameId = glGetUniformLocation(shaderProgram, _name.c_str());/*将4x4的矩阵数据传递给着色器location:指定要更改的uniform变量的位置。count:指定要更改的矩阵的数量。如果只更改一个矩阵,该值为1。transpose:指定是否需要将矩阵进行转置。一般情况下,设为GL_FALSE即可。value:指向包含矩阵数据的指针。*/glUniformMatrix4fv(shaderNameId,1,GL_FALSE,glm::value_ptr(_matrix));
}void OpenGLClass::FlushRender()
{// 判断VAO是否被删除if (glIsVertexArray(VAO)){// 使用红,绿,蓝以及alpha值来清除颜色缓冲区glClearColor(0.328125f, 0.35156f, 0.82421f, 1.0f);// 将从窗口中清除最后一次所绘制的图形,GL_DEPTH_BUFFER_BIT将深度信息也清除glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 开启深度检测glEnable(GL_DEPTH_TEST);///		// 模型平移数据glm::vec3 modelVecs[] ={glm::vec3(0.0f,0.0f,0.0f),glm::vec3(2.0f, 5.0f, -15.0f),glm::vec3(-1.5f, -2.2f, -2.5f),glm::vec3(-3.8f, -2.0f, -12.3f),glm::vec3(2.4f, -0.4f, -3.5f),glm::vec3(-1.7f, 3.0f, -7.5f),glm::vec3(1.3f, -2.0f, -2.5f),glm::vec3(1.5f, 2.0f, -2.5f),glm::vec3(1.5f, 0.2f, -1.5f),glm::vec3(-1.3f, 1.0f, -1.5f)};//////// 观察者/摄像机矩阵
#if 0glm::mat4 _viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 2.4f),	// 摄像机位置glm::vec3(0.0f, 0.0f, 0.0f),	// 摄像机看向的位置glm::vec3(0.0f, 1.0f, 0.0f)		// 摄像机顶部的位置);
#else_camera.update();
#endif// 投影矩阵glm::mat4 _projMatrix = glm::perspective(glm::radians(45.0f),(float)windowWidth / (float)(windowHeight),0.1f, 100.0f);///#if 0// 使用程序glUseProgram(shaderProgram);///setMatrix("_viewMatrix", _viewMatrix);setMatrix("_projMatrix", _projMatrix);///// 绑定纹理glBindTexture(GL_TEXTURE_2D, _texture);// 绑定VAOglBindVertexArray(VAO);// 绘制三角形glDrawArrays(GL_TRIANGLES, 0, 36);// 关闭使用程序glUseProgram(0);
#else// 使用程序glUseProgram(shaderProgram);// 绘制10个立方体for (unsigned short index = 0; index < 10; ++index){glm::mat4 _modelMatrix(1.0f);_modelMatrix = glm::translate(_modelMatrix, modelVecs[index]);_modelMatrix = glm::rotate(_modelMatrix, glm::radians((float)glfwGetTime()*(index + 1) * 10), glm::vec3(0.5f, 1.0f, 0.0f));///setMatrix("_modelMatrix", _modelMatrix);setMatrix("_viewMatrix", _camera.getMatrix());setMatrix("_projMatrix", _projMatrix);///// 绑定纹理glBindTexture(GL_TEXTURE_2D, _texture);// 绑定VAOglBindVertexArray(VAO);// 绘制三角形glDrawArrays(GL_TRIANGLES, 0, 36);}// 关闭使用程序glUseProgram(0);
#endif}
}bool OpenGLClass::initTexture()
{// 读取图片相关信息ffImage *pImage = ffImage::readFromFile("./rec/wall.jpeg");if (!pImage) { return false; }// 生成纹理glGenTextures(1, &_texture);// 以2D方式绑定纹理// 将当前绑定的纹理对象替换为参数中指定的纹理对象glBindTexture(GL_TEXTURE_2D, _texture);// 设置纹理属性glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 读取图片数据,完成数据绑定glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pImage->getWidth(), pImage->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pImage->getData());if (pImage) { delete pImage; }pImage = nullptr;return true;
}void OpenGLClass::initModel()
{// 坐标、颜色、纹理位置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};/****************************************************/	// VAO// 创建VAOglGenVertexArrays(1, &VAO);// 绑定指定的顶点数组对象(Vertex Array Object, VAO)glBindVertexArray(VAO);/****************************************************//****************************************************/	// VBO// 生成缓冲区对象glGenBuffers(1, &VBO);// 绑定命名缓冲区对象glBindBuffer(GL_ARRAY_BUFFER, VBO);// 缓冲对象(VBO,IBO 等)分配空间并存储数据glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);/*指定顶点属性在顶点缓冲对象中的布局,并将其与顶点着色器中的顶点属性进行关联参数1:第n个layout (对应glsl中顶点着色器的layout)参数2:顶点属性的组成元素的数量,例如3表示顶点属性是由3个浮点数组成参数3:顶点属性的数据类型参数4:是否将非浮点型的数据归一化到[-1, 1]或[0, 1]范围内参数5:相邻两个顶点属性之间的字节数,通常为0或属性类型大小乘以数量参数6:顶点属性在顶点缓冲对象中的偏移量或者数据的首地址*/glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(sizeof(float) * 3));// 激活锚点(参数:第n个layout)glEnableVertexAttribArray(0);glEnableVertexAttribArray(1);// 解绑VAO/VBOglBindVertexArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);/****************************************************/
}std::string OpenGLClass::ReadGlslContext(const char *sPath)
{std::string strContext;if (!sPath) { return strContext; }std::ifstream sFile;sFile.open(sPath);if (sFile.is_open()){std::stringstream sStream;sStream << sFile.rdbuf();strContext = sStream.str();}return strContext;
}bool OpenGLClass::initShader(const char *_vertexPath, const char *_fragPath)
{char infoLog[512] = { 0 };int successFlag = 0;/*********************************************************/	// vertex编译std::string vertexContext = ReadGlslContext(_vertexPath); if (vertexContext.empty()) { return false; }const char *cVertexContext = vertexContext.c_str();// 创建顶点着色器对象unsigned int iVertexID = glCreateShader(GL_VERTEX_SHADER);// 为顶点着色器指定源码(参数2:传过去几个)glShaderSource(iVertexID, 1, &cVertexContext, nullptr);// 编译顶点着色器源码glCompileShader(iVertexID);// 查看编译顶点着色器源码结果glGetShaderiv(iVertexID, GL_COMPILE_STATUS, &successFlag);if (!successFlag)	// 编译失败{// 获取编译失败原因glGetShaderInfoLog(iVertexID, 512, nullptr, infoLog);std::cout << "glGetShaderiv GL_VERTEX_SHADER" << iVertexID << " fail:" << infoLog << std::endl; return false;}cVertexContext = nullptr;/*********************************************************//*********************************************************/	// fragment编译std::string fragmentContext = ReadGlslContext(_fragPath); if (fragmentContext.empty()) { return false; }const char *cFragmentContext = fragmentContext.c_str();// 创建片段着色器对象unsigned int iFragmentID = glCreateShader(GL_FRAGMENT_SHADER);// 为片段着色器指定源码(参数2:传过去几个)glShaderSource(iFragmentID, 1, &cFragmentContext, nullptr);// 编译片段着色器源码glCompileShader(iFragmentID);// 查看编译片段着色器源码结果glGetShaderiv(iFragmentID, GL_COMPILE_STATUS, &successFlag);if (!successFlag)	// 编译失败{// 获取编译失败原因glGetShaderInfoLog(iFragmentID, 512, nullptr, infoLog);std::cout << "glGetShaderiv GL_FRAGMENT_SHADER" << iFragmentID << " fail:" << infoLog << std::endl; return false;}cFragmentContext = nullptr;/*********************************************************//*********************************************************/	// 链接// 创建一个空的程序对象shaderProgram = glCreateProgram();if (shaderProgram == 0) { std::cout << "glCreateProgram fail!\n"; return false; }// 将着色器对象附加到程序对象上(注:glDetachShader为移除程序对象中的指定着色器对象)glAttachShader(shaderProgram, iVertexID);glAttachShader(shaderProgram, iFragmentID);// 进行链接程序对象glLinkProgram(shaderProgram);// 查看链接状态glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successFlag);if (!successFlag)	// 链接失败{// 获取链接失败原因glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);std::cout << "glGetProgramiv " << shaderProgram << " fail:" << infoLog << std::endl; return false;}/*********************************************************//* 在链接完成后,将编译shader相关删除。仅留下链接ID */if (glIsShader(iVertexID)) { glDeleteShader(iVertexID); }if (glIsShader(iFragmentID)) { glDeleteShader(iFragmentID); }return true;
}

          OpenGLClass.h

#pragma once#include "Global.h"
#include "ffImage.h"
#include "Camera.h"class OpenGLClass
{
public:OpenGLClass();~OpenGLClass();protected:// 初始化纹理bool initTexture();// 初始化模型VAO/VBOvoid initModel();// 初始化shader文件bool initShader(const char *_vertexPath, const char *_fragPath);// 读取glsl文件内容std::string ReadGlslContext(const char *sPath);// 刷新Rendervoid FlushRender();// 回调 - 窗口尺寸变化回调static void bck_GLFWframebuffersizefun(GLFWwindow* window, int width, int height);// 处理按键输入void ProcessKeyPInput(GLFWwindow *window);// 设置矩阵void setMatrix(const std::string &_name, glm::mat4 _matrix)const;private:unsigned short windowWidth = 800, windowHeight = 600;unsigned int shaderProgram = 0;		// 链接程序对象unsigned int VBO = 0, VAO = 0, _texture = 0;Camera _camera;
};

          Camera.cpp

#include "Camera.h"Camera::Camera()
{
}Camera::~Camera()
{
}void Camera::setSpeed(float _spped)
{if (_spped > 0 && _spped < 0.5){m_speed = _spped;}
}float Camera::getSpeed()
{return m_speed;
}void Camera::lookAt(glm::vec3 _pos, glm::vec3 _front, glm::vec3 _up)
{InitialPosition = _pos;m_position = _pos;m_front = glm::normalize(_front);m_up = _up;m_vMatrix = glm::lookAt(m_position, m_position + m_front, m_up);
}void Camera::update()
{m_vMatrix = glm::lookAt(m_position, m_position + m_front, m_up);
}glm::mat4 Camera::getMatrix()
{return m_vMatrix;
}void Camera::move(CAMERA_MOVE _mode)
{switch (_mode){case CAMERA_MOVE::MOVE_LEFT:m_position -= glm::normalize(glm::cross(m_front, m_up)) * m_speed;break;case CAMERA_MOVE::MOVE_RIGHT:m_position += glm::normalize(glm::cross(m_front, m_up)) * m_speed;break;case CAMERA_MOVE::MOVE_FRONT:m_position += m_speed * m_front;break;case CAMERA_MOVE::MOVE_BACK:m_position -= m_speed * m_front;break;case CAMERA_MOVE::MOVE_UP:m_position += glm::normalize(glm::cross(glm::vec3(1.0f, 0.0f, 0.0f), m_front))*m_speed;break;case CAMERA_MOVE::MOVE_DOWN:m_position -= glm::normalize(glm::cross(glm::vec3(1.0f, 0.0f, 0.0f), m_front))*m_speed;break;case CAMERA_MOVE::MOVE_InitialPosition:m_position = InitialPosition;break;default:break;}
}

          Camera.h

#pragma once#include "Global.h"enum class CAMERA_MOVE
{MOVE_LEFT,MOVE_RIGHT,MOVE_FRONT,MOVE_BACK,MOVE_UP,MOVE_DOWN,MOVE_InitialPosition
};class Camera
{
public:Camera();~Camera();void setSpeed(float);float getSpeed();void lookAt(glm::vec3 _pos, glm::vec3 _front, glm::vec3 _up);void update();glm::mat4 getMatrix();void move(CAMERA_MOVE);private:glm::vec3 m_position = glm::vec3(1.0f), InitialPosition = glm::vec3(1.0f);glm::vec3 m_front = glm::vec3(1.0f);glm::vec3 m_up = glm::vec3(1.0f);float m_speed = 0.01f;glm::mat4 m_vMatrix = glm::mat4(1.0f);
};

完整源码下载

      源码下载

关注

Wx GZH:码农总动员

笔者 - jxd

相关文章:

OpenGL —— 2.8、漫游之摄像机飞行移动(附源码,glfw+glad)

源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库&#xff0c;该库只有一个头文件。 具体代码&#xff1a; vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec2 aUV;out vec2 outUV;uniform mat4 _modelMatrix; …...

AM@麦克劳林公式逼近以及误差分析

abstract 麦克劳林公式及其近似表示的应用误差估计和分析 Lagrange型泰勒公式的估计误差 由Lagrange型余项泰勒公式可知,多项式 p n ( x ) p_n(x) pn​(x)近似表达函数 f ( x ) f(x) f(x)时,其误差为 ∣ R n ( x ) ∣ |R_{n}(x)| ∣Rn​(x)∣ R n ( x ) R_{n}(x) Rn​(x) f …...

gitlab 离线安装问题解决:NOKEY,signature check fail

1&#xff0c;rpm安装gitlab问题 test1:/opt # rpm -ivh gitlab-ce-16.0.3-ce.0.el7.x86_64.rpm --force warning: gitlab-ce-16.0.3-ce.0.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID f27eab47: NOKEY error: [upel]: gitlab-ce NOKEY error: [upel]: gitlab-ce …...

uniapp使用uQRCode绘制二维码,下载到本地,调起微信扫一扫二维码核销

1.效果 2.在utils文件夹下创建uqrcode.js // uqrcode.js //--------------------------------------------------------------------- // github https://github.com/Sansnn/uQRCode //---------------------------------------------------------------------let uQRCode {…...

手写一个PrattParser基本运算解析器3: 基于Swift的PrattParser的项目概述

点击查看 基于Swift的PrattParser项目 PrattParser项目概述 前段时间一直想着手恶补 编译原理 的相关知识, 一开始打算直接读大学的 编译原理, 虽然内容丰富, 但是着实抽象难懂. 无意间看到B站的熊爷关于普拉特解析器相关内容, 感觉是一个非常好的切入点.所以就写了基于Swift版…...

三江学院“火焰杯”软件测试高校就业选拔赛颁奖仪式

11月25日下午&#xff0c;“火焰杯”软件测试开发选拔赛及三江-慧科卓越工程师班暑期编程能力训练营颁奖仪式在s楼会议室隆重举行。计算机科学与工程学院院长刘亚军、副院长叶传标、曹阳、吴德、院党总支副书记王兰英、系主任杨少雄、慧科企业代表尹沁伊人、项目负责人王旭出席…...

面试题-消息中间件篇-主流的消息中间件

消息中间件篇 第一章 主流的消息中间件对比 1、主流的消息中间件有 Kafka、RabbitMQ、ActiveMQ 等。 Kafka&#xff1a; Kafka 是一种高吞吐量、分布式、可扩展的发布/订阅消息系统&#xff0c;主要用于大数据处理和分析。Kafka 采用消息日志的方式来存储消息&#xff0c;可以…...

PyQt学习笔记-获取Hash值的小工具

目录 一、概述1.1 版本信息&#xff1a;1.2 基本信息&#xff1a;1.2.1 软件支持的内容&#xff1a;1.2.2 支持的编码格式 1.3 软件界面图 二、代码实现2.1 View2.2 Controller2.3 Model 三、测试示例 一、概述 本工具居于hashlibPyQtQFileDialog写的小工具&#xff0c;主要是…...

【(数据结构)— 双向链表的实现】

&#xff08;数据结构&#xff09;— 双向链表的实现 一.双向链表的结构二. 双向链表的实现2.1 头文件 ——双向链表的创建及功能函数的定义2.2 源文件 ——双向链表的功能函数的实现2.3 源文件 ——双向链表功能的测试2.4 双向链表各项功能测试运行展示2.4.1 双向链表的初始化…...

酷克数据发布HD-SQL-LLaMA模型,开启数据分析“人人可及”新时代

随着行业数字化进入深水区&#xff0c;企业的关注点正在不断从“数字”价值转向“数智”价值。然而&#xff0c;传统数据分析的操作门槛与时间成本成为了掣肘数据价值释放的阻力。常规的数据分析流程复杂冗长&#xff0c;需要数据库管理员设计数据模型&#xff0c;数据工程师进…...

FL Studio21最新中文破解进阶高级完整版安装下载教程

目前水果软件最版本是FL Studio21&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破想象力的限制。喜欢音乐制作的小伙伴千万不要错过这个功能强大&#xff0c;安装便捷的音乐软件哦&#xff01;如…...

MDN--Web性能

CSS 动画与 JavaScript 动画 动画的实现可以有很多种方式&#xff0c;比如 CSS transition 和 animation 或者基于 JavaScript 的动画(使用 requestAnimationFrame()) CSS 过渡和动画 CSS transiton :创建当前样式与结束状态样式之间的动画。尽管一个元素处于过渡状态中&…...

Vue3.js:自定义组件 v-model

Vue3的自定义v-model和vue2稍有不同 文档 https://cn.vuejs.org/guide/components/v-model.html 目录 原生组件自定义组件CustomInput实现代码1CustomInput实现代码2 v-model 的参数 原生组件 <input v-model"searchText" />等价于 <input:value"s…...

AI虚拟主播开发实战(附源码)

人工智能 文章目录 人工智能前言 前言 https://blog.csdn.net/icemanyandy/article/details/124035967...

innoDB如何解决幻读

Mysql的事务隔离级别 Mysql 有四种事务隔离级别&#xff0c;这四种隔离级别代表当存在多个事务并发冲突时&#xff0c;可能出现的脏读、不可重复读、幻读的问题。其中 InnoDB 在 RR 的隔离级别下&#xff0c;解决了幻读的问题 事务隔离级别脏读不可重复读幻读未提交读&#xff…...

Git - 导出(archive)、忽略(gitignore)、隐藏(Stash)、合并冲突(merge)的解决方法

概述 本次集中总结了Git4个常规操作&#xff0c;导出(archive)、忽略(gitignore)、隐藏(Stash)、合并冲突(merge)的解决方法&#xff0c;希望帮助到正在辛苦寻找的你。 .gitignore忽略文件 之前开发和部署服务比较仓促&#xff0c;所以有很多图片文件一起加载到服务中&#…...

【Javascript】‘var‘ is used instead of ‘let‘ or ‘const‘

解决&#xff1a; 设置完之后,var 就不会再出现黄色波浪线警告...

金融统计学方法:神经网络

目录 1.神经网络 2.深度神经网络 3.案例分析 1.神经网络 神经网络是模仿人脑神经元工作原理而设计的一种算法模型。在一个基本的神经网络中&#xff0c;存在多个“神经元”或称为“节点”&#xff0c;这些节点被组织成多个层次。每个节点都接收前一层的输入&#xff0c;进行…...

任何人不知道这款超实用的配音软件,我都会伤心的OK?

看完一段精彩的视频&#xff0c;令人陶醉的原因之一就是配音&#xff0c;有的充满感情&#xff0c;有的字正腔圆&#xff0c;相信很多人都不知道这样的声音是怎么配出来的&#xff1f;今天&#xff0c;小编就来给大家分享一款超实用的配音软件&#xff0c;不仅操作简单&#xf…...

Linux查看日志文件的常用命令

1、查看文件最后1000行内容 tail -n 1000 filename 2、实时查看文件最后1000行内容&#xff0c;动态刷新 tailf -n 1000 filename tail -f -n 1000 filename 3、按照关键字搜索日志 cat filename | grep 关键字 4、按照关键字搜索并包含前(后)多少行 【&#xff08;A前B后C前…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...