OpenGL —— 2.6、绘制一个正方体并贴图(附源码,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 _viewMatrix;
uniform mat4 _projMatrix;void main()
{gl_Position = _projMatrix * _viewMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);outUV = aUV;
}
fragmentShader.glsl
#version 330 coreout vec4 FragColor;in vec2 outUV;uniform sampler2D ourTexture;void main()
{// 使用图片纹理及色彩混合FragColor = texture(ourTexture, outUV);
}
main.cpp
#include "OpenGLClass.h"
#include "OpenGLClass.h"int main()
{OpenGLClass opengl;return 0;
}
OpenGLClass.h
#pragma once#include "Global.h"
#include "ffImage.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;
};
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);// 初始化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){// 获取窗口按键是否ESCif (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){// 设置窗口关闭标志glfwSetWindowShouldClose(window, true);}}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::mat4 _viewMatrix = glm::lookAt(glm::vec3(1.4f, 1.4f, 2.0f), // 摄像机位置glm::vec3(0.0f, 0.0f, 0.0f), // 摄像机看向的位置glm::vec3(0.0f, 1.0f, 0.0f) // 摄像机顶部的位置);// 投影矩阵glm::mat4 _projMatrix = glm::perspective(glm::radians(45.0f),(float)windowWidth / (float)(windowHeight),0.1f, 100.0f);///// 使用程序glUseProgram(shaderProgram);///setMatrix("_viewMatrix", _viewMatrix);setMatrix("_projMatrix", _projMatrix);///// 绑定纹理glBindTexture(GL_TEXTURE_2D, _texture);// 绑定VAOglBindVertexArray(VAO);// 绘制三角形glDrawArrays(GL_TRIANGLES, 0, 36);// 关闭使用程序glUseProgram(0);}
}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;
}
完整源码下载
源码下载
关注
Wx GZH:码农总动员
笔者 - jxd
相关文章:
OpenGL —— 2.6、绘制一个正方体并贴图(附源码,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 _viewMatrix; u…...
JavaWeb从入门到起飞笔记——导学课程
学完这一节,我不知道学Web开发究竟能干什么?你知道吗? 以下是黑马程序员Java从入门到起飞的笔记 一、学完Javaweb能干什么? 学完Java后我们可以独立开发一些后台管理系统,例如CRMER器,京东和淘宝&#x…...
【LeetCode:1402. 做菜顺序 | 动态规划 + 贪心】
🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…...
基于FPGA的图像拉普拉斯变换实现,包括tb测试文件和MATLAB辅助验证
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a vivado2019.2 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 202…...
高校教务系统登录页面JS分析——巢湖学院
高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文,你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习,勿用于非法用途。 一、密码加…...
人工智能、机器学习、深度学习的区别
人工智能涵盖范围最广,它包含了机器学习;而机器学习是人工智能的重要研究内容,它又包含了深度学习。 人工智能(AI) 人工智能是一门以计算机科学为基础,融合了数学、神经学、心理学、控制学等多个科目的交…...
Element Plus el-select选择框失去焦点blur
正常情况下,可以使用 el-select 自带的方法 blur 事件来使select失去焦点 示例: <el-select v-model"value" ref"selectRef"><el-optionv-for"item in options":key"item.value":label"item.la…...
Java File与IO流学习笔记
内存中存放的都是临时数据,但是在断电或者程序终止时都会丢失 而硬盘则可以长久存储数据,即使断电,程序终止,也不会丢失 File File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文…...
LabVIEW中PID控制的的高级功能
LabVIEW中PID控制的的高级功能 比例-积分-微分(PID)控制占当今控制和自动化应用的90%以上,主要是因为它是一种有效且简单的解决方案。虽然PID算法最初用于线性、时不变系统,但现在已经发展到控制具有复杂动力学的系统。在现实世界…...
STM32基于HAL库RT-Thread Demo测试
STM32基于HAL库RT-Thread Demo测试 🎈源码地址:https://github.com/RT-Thread/rt-thread/tree/master📌基于STM32CUBEMX中间件安装《基于 CubeMX 移植 RT-Thread Nano》📍环境搭建《使用 Env 创建 RT-Thread 项目工程》ǵ…...
萌新小白必做题(2)找素数
一.思路分析 先来看看素数的性质: 素数又称质数,是指除了1和本身外没有其它因数的自然数。素数有许多有趣的性质和应用,例如可以用于加密算法和数学证明等。比如2、3、5、7等都是素数,而4、6、8、9等则不是素数。素数的研究是数…...
《基于 Vue 组件库 的 Webpack5 配置》8.在生成打包文件之前清空 output(dist) 目录(两种方式)
方式一 如果 webpack 是 v5.20.0,直接使用属性 output.clean,配置如下: module.exports {//...output: {clean: true}, };方式二 如果使用较低版本,可以使用插件 clean-webpack-plugin: 先安装:npm…...
3、Kafka Broker
4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 (1)启动 Zookeeper 客户端。 [hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh(2)通过 ls 命令可以查看 kafka 相关信息。 [zk: localhost:2181(CONNECTED) 2] ls /kaf…...
数字孪生智慧建筑可视化系统,提高施工效率和建造质量
随着科技的不断进步和数字化的快速发展,数字孪生成为了建筑行业的一个重要的概念,被广泛应用于智能化建筑的开发与管理中。数字孪生是将现实世界的实体与数字世界的虚拟模型进行连接和同步,从而实现实时的数据交互和模拟仿真。数字孪生在建筑…...
SpringCloud: feign整合sentinel实现降级
一、加依赖: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache…...
List<LinkedHashMap<String, String>>类型的数据转换为Map<String, List<String>>类型数据
import java.util.*;public class Main {public static void main(String[] args) {// 示例数据:List<LinkedHashMap>List<LinkedHashMap<String, String>> keyParamList new ArrayList<>();LinkedHashMap<String, String> map1 ne…...
react 学习 —— 16、使用 ref 操作 DOM
什么时候使用 ref 操作 DOM? 有时你可能需要访问由 React 管理的 DOM 元素 —— 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM 节点的 ref 来实现。 怎么使用 r…...
Qt planeGame day10
Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用,我们需要自己搭框架首先创建一个QGame类作为框架,这个基本框架里面应该有如下功能:游戏初始化 void init(const QSize& siez,const QString& title);游戏反初始化(…...
贪吃蛇项目实践
游戏背景: 贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的⾏列。 实现基本的功能: 贪吃蛇地图绘制 蛇吃⻝物的功能 (上、下、左、右⽅向键控制蛇的动作) 蛇撞墙死亡 蛇撞⾃⾝死亡 计…...
【C++】哈希应用——海量数据面试题
哈希应用——海量数据面试题 一、位图应用1、给定100亿个整数,设计算法找到只出现一次的整数?2、给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?(1)用一个位图…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
