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

Open GL ES ->纹理贴图,顶点坐标和纹理坐标组合到同一个顶点缓冲对象中进行解析

XML文件

<?xml version="1.0" encoding="utf-8"?>
<com.example.myapplication.MyGLSurfaceView2 xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/glSurfaceView"android:layout_width="match_parent"android:layout_height="match_parent" />

Activity代码

class MainActivity6 : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main6)}
}

GLSurfaceView代码

class MyGLSurfaceView2(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs) {private var mRenderer = MyMatrixRenderer2(context)init {// 设置 OpenGL ES 3.0 版本setEGLContextClientVersion(3)setRenderer(mRenderer)// 设置渲染模式, 仅在需要重新绘制时才进行渲染,以节省资源renderMode = RENDERMODE_WHEN_DIRTY}
}

GLSurfaceView.Renderer代码

class MyMatrixRenderer2(private val mContext: Context) : GLSurfaceView.Renderer {var mDrawData: MyDrawData2? = nulloverride fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {// 当 Surface 创建时调用, 进行 OpenGL ES 环境的初始化操作, 设置清屏颜色为青蓝色 (Red=0, Green=0.5, Blue=0.5, Alpha=1)GLES30.glClearColor(0.0f, 0.5f, 0.5f, 1.0f)mDrawData = MyDrawData2().apply {initTexture0(mContext, R.drawable.picture)initShaderProgram()initVertexBuffer()}}override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {// 当 Surface 尺寸发生变化时调用,例如设备的屏幕方向发生改变, 设置视口为新的尺寸,视口是指渲染区域的大小GLES30.glViewport(0, 0, width, height)mDrawData?.resetMatrix()mDrawData?.computeMVPMatrix(width, height)}override fun onDrawFrame(gl: GL10?) {GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)mDrawData?.drawCurrentOutput()}
}

GLSurfaceView.Renderer需要的绘制数据

class MyDrawData2 {private var mProgram: Int = -1private var NO_OFFSET = 0private val VERTEX_POS_DATA_SIZE = 3private val TEXTURE_POS_DATA_SIZE = 2private val STRIDE = (VERTEX_POS_DATA_SIZE + TEXTURE_POS_DATA_SIZE) * 4 // 每个顶点的总字节数// VAO(Vertex Array Object), 顶点数组对象, 用于存储VBOprivate var mVAO = IntArray(1)// VBO(Vertex Buffer Object), 顶点缓冲对象,用于存储顶点数据和纹理数据private var mVBO = IntArray(1) // 只需要一个VBO// IBO(Index Buffer Object), 索引缓冲对象,用于存储顶点索引数据private var mIBO = IntArray(1)// 纹理IDprivate var mTextureID = IntArray(1)// 最终变换矩阵private var mMVPMatrix = FloatArray(16)// 投影矩阵private val mProjectionMatrix = FloatArray(16)// 视图矩阵private val mViewMatrix = FloatArray(16)// 模型矩阵private val mModelMatrix = FloatArray(16)// 视口比例private var mViewPortRatio = 1f// 顶点和纹理坐标合并在一个数组中// 格式:x, y, z, u, v (顶点坐标后跟纹理坐标)val vertexData = floatArrayOf(// 顶点坐标            // 纹理坐标-1.0f, 1.0f, 0.0f,    0.0f, 1.0f, // 左上-1.0f, -1.0f, 0.0f,   0.0f, 0.0f, // 左下1.0f, 1.0f, 0.0f,     1.0f, 1.0f, // 右上1.0f, -1.0f, 0.0f,    1.0f, 0.0f  // 右下)val vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexData).position(NO_OFFSET)val index = shortArrayOf(0, 1, 2, // 第一个三角形1, 3, 2  // 第二个三角形)val indexBuffer = ByteBuffer.allocateDirect(index.size * 2).order(ByteOrder.nativeOrder()).asShortBuffer().put(index).position(NO_OFFSET)// 初始化着色器程序fun initShaderProgram() {val vertexShaderCode = """#version 300 esuniform mat4 uMVPMatrix; // 变换矩阵in vec4 aPosition; // 顶点坐标in vec2 aTexCoord; // 纹理坐标 out vec2 vTexCoord; void main() {// 输出顶点坐标和纹理坐标到片段着色器gl_Position = uMVPMatrix * aPosition;vTexCoord = aTexCoord;}""".trimIndent()val fragmentShaderCode = """#version 300 esprecision mediump float;uniform sampler2D uTexture_0;in vec2 vTexCoord;out vec4 fragColor;void main() {fragColor = texture(uTexture_0, vTexCoord);}""".trimIndent()// 加载顶点着色器和片段着色器, 并创建着色器程序val vertexShader = LoadShaderUtil.loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)val fragmentShader = LoadShaderUtil.loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)mProgram = GLES30.glCreateProgram()GLES30.glAttachShader(mProgram, vertexShader)GLES30.glAttachShader(mProgram, fragmentShader)GLES30.glLinkProgram(mProgram)// 删除着色器对象GLES30.glDeleteShader(vertexShader)GLES30.glDeleteShader(fragmentShader)}// 创建VAO, VBO, IBOfun initVertexBuffer() {// 绑定VAOGLES30.glGenVertexArrays(mVAO.size, mVAO, NO_OFFSET)GLES30.glBindVertexArray(mVAO[0])// 绑定VBO - 只需要一个VBO存储所有数据GLES30.glGenBuffers(mVBO.size, mVBO, NO_OFFSET)GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBO[0])GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexData.size * 4,vertexDataBuffer,GLES30.GL_STATIC_DRAW)// 设置顶点属性指针 - 顶点坐标val positionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition")GLES30.glEnableVertexAttribArray(positionHandle)GLES30.glVertexAttribPointer(positionHandle,VERTEX_POS_DATA_SIZE,GLES30.GL_FLOAT,false,STRIDE,     // 步长,每个顶点5个float (x,y,z,u,v)NO_OFFSET   // 偏移量,位置数据在前)// 设置顶点属性指针 - 纹理坐标val textureHandle = GLES30.glGetAttribLocation(mProgram, "aTexCoord")GLES30.glEnableVertexAttribArray(textureHandle)GLES30.glVertexAttribPointer(textureHandle,TEXTURE_POS_DATA_SIZE,GLES30.GL_FLOAT,false,STRIDE,                          // 步长,每个顶点5个float (x,y,z,u,v)VERTEX_POS_DATA_SIZE * 4         // 偏移量,纹理数据在位置数据之后)// 绑定IBOGLES30.glGenBuffers(mIBO.size, mIBO, NO_OFFSET)// 绑定索引缓冲区数据到IBO[0]GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, mIBO[0])GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,index.size * 2,indexBuffer,GLES30.GL_STATIC_DRAW)// 解绑VAOGLES30.glBindVertexArray(0)// 解绑VBO和IBOGLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)}// 使用着色器程序绘制图形fun drawSomething(program: Int, mvpMatrix: FloatArray) {// 解析变换矩阵val matrixHandle = GLES30.glGetUniformLocation(program, "uMVPMatrix")GLES30.glUniformMatrix4fv(matrixHandle, 1, false, mvpMatrix, NO_OFFSET)// 绑定VAOGLES30.glBindVertexArray(mVAO[0])// 绘制图形GLES30.glDrawElements(GLES30.GL_TRIANGLES,index.size,GLES30.GL_UNSIGNED_SHORT,NO_OFFSET)// 解绑VAOGLES30.glBindVertexArray(0)}fun resetMatrix() {Matrix.setIdentityM(mModelMatrix, NO_OFFSET)Matrix.setIdentityM(mViewMatrix, NO_OFFSET)Matrix.setIdentityM(mProjectionMatrix, NO_OFFSET)Matrix.setIdentityM(mMVPMatrix, NO_OFFSET)}// 计算GLSurfaceView变换矩阵fun computeMVPMatrix(width: Int, height: Int) {val isLandscape = width > heightmViewPortRatio = if (isLandscape) width.toFloat() / height else height.toFloat() / width// 计算包围图片的球半径val radius = sqrt(1f + mViewPortRatio * mViewPortRatio)val near = 0.1fval far = near + 2 * radiusval distance = near / (near + radius)// 视图矩阵View MatrixMatrix.setLookAtM(mViewMatrix, NO_OFFSET,0f, 0f, near + radius,  // 相机位置0f, 0f, 0f,             // 看向原点0f, 1f, 0f              // 上方向)// 投影矩阵Projection MatrixMatrix.frustumM(mProjectionMatrix, NO_OFFSET,if (isLandscape) (-mViewPortRatio * distance) else (-1f * distance),  // 左边界if (isLandscape) (mViewPortRatio * distance) else (1f * distance),    // 右边界if (isLandscape) (-1f * distance) else (-mViewPortRatio  * distance),  // 下边界if (isLandscape) (1f * distance) else (mViewPortRatio * distance),    // 上边界near, // 近平面far // 远平面)// 最终变换矩阵,第一次变换,模型矩阵 x 视图矩阵 = Model x View, 但是OpenGL ES矩阵乘法是右乘,所以是View x ModelMatrix.multiplyMM(mMVPMatrix,NO_OFFSET,mViewMatrix,NO_OFFSET,mModelMatrix,NO_OFFSET)// 最终变换矩阵,第二次变换,模型矩阵 x 视图矩阵 x 投影矩阵 = Model x View x Projection, 但是OpenGL ES矩阵乘法是右乘,所以是Projection x View x ModelMatrix.multiplyMM(mMVPMatrix,NO_OFFSET,mProjectionMatrix,NO_OFFSET,mMVPMatrix,NO_OFFSET)// 纹理坐标系为(0, 0), (1, 0), (1, 1), (0, 1)的正方形逆时针坐标系,从Bitmap生成纹理,即像素拷贝到纹理坐标系// 变换矩阵需要加上一个y方向的翻转, x方向和z方向不改变Matrix.scaleM(mMVPMatrix,NO_OFFSET,1f,-1f,1f,)}// 加载纹理fun loadTexture(context: Context, resourceId: Int): Int {val textureId = IntArray(1)// 生成纹理GLES30.glGenTextures(1, textureId, 0)// 绑定纹理GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId[0])// 设置纹理参数GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MIN_FILTER,GLES30.GL_LINEAR) // 纹理缩小时使用线性插值GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MAG_FILTER,GLES30.GL_LINEAR) // 纹理放大时使用线性插值GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_WRAP_S,GLES30.GL_CLAMP_TO_EDGE) // 纹理坐标超出范围时,超出部分使用最边缘像素进行填充GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_WRAP_T,GLES30.GL_CLAMP_TO_EDGE) // 纹理坐标超出范围时,超出部分使用最边缘像素进行填充// 加载图片val options = BitmapFactory.Options().apply {inScaled = false // 不进行缩放}val bitmap = BitmapFactory.decodeResource(context.resources, resourceId, options)// 将图片数据加载到纹理中GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0)// 释放资源bitmap.recycle()// 解绑纹理GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)Log.e("yang","loadTexture: 纹理加载成功 bitmap.width:${bitmap.width} bitmap.height:${bitmap.height}")return textureId[0]}fun enableTexture0(program: Int, id: Int) {GLES30.glActiveTexture(GLES30.GL_TEXTURE0)GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, id)val textureSampleHandle = GLES30.glGetUniformLocation(program, "uTexture_0")if (textureSampleHandle != -1) {GLES30.glUniform1i(textureSampleHandle, 0)}}fun disableTexture0() {GLES30.glActiveTexture(GLES30.GL_TEXTURE0)GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)}fun initTexture0(context: Context, resourceId: Int) {mTextureID[0] = loadTexture(context, resourceId)}// GLSurfaceView实时绘制fun drawCurrentOutput() {val state = saveGLState()try {GLES30.glUseProgram(mProgram)enableTexture0(mProgram, mTextureID[0])drawSomething(mProgram, mMVPMatrix)disableTexture0()} finally {restoreGLState(state)}}// 保存OpenGL状态private fun saveGLState(): GLState {val viewport = IntArray(4)val program = IntArray(1)val framebuffer = IntArray(1)GLES30.glGetIntegerv(GLES30.GL_VIEWPORT, viewport, 0)GLES30.glGetIntegerv(GLES30.GL_CURRENT_PROGRAM, program, 0)GLES30.glGetIntegerv(GLES30.GL_FRAMEBUFFER_BINDING, framebuffer, 0)return GLState(viewport, program[0], framebuffer[0])}// 恢复OpenGL状态private fun restoreGLState(state: GLState) {GLES30.glViewport(state.viewport[0],state.viewport[1],state.viewport[2],state.viewport[3])GLES30.glUseProgram(state.program)GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, state.framebuffer)}// OpenGL状态数据类data class GLState(val viewport: IntArray,val program: Int,val framebuffer: Int)object LoadShaderUtil {// 创建着色器对象fun loadShader(type: Int, source: String): Int {val shader = GLES30.glCreateShader(type)GLES30.glShaderSource(shader, source)GLES30.glCompileShader(shader)return shader}}
}

解析说明

顶点坐标和纹理坐标的存储

  • 顶点坐标的四个角和纹理坐标的四个角进行对应,顶点由(x, y, z)三个点构成,纹理由(u, v)两个点构成
// 顶点和纹理坐标合并在一个数组中
// 格式:x, y, z, u, v (顶点坐标后跟纹理坐标)
val vertexData = floatArrayOf(// 顶点坐标            // 纹理坐标-1.0f, 1.0f, 0.0f,    0.0f, 1.0f, // 左上-1.0f, -1.0f, 0.0f,   0.0f, 0.0f, // 左下1.0f, 1.0f, 0.0f,     1.0f, 1.0f, // 右上1.0f, -1.0f, 0.0f,    1.0f, 0.0f  // 右下
)

顶点坐标和纹理坐标的解析

    1. 生成并绑定需要存储顶点坐标和纹理坐标的顶点缓冲对象(Vertex Buffer Object)VBO
    • 方法: GLES30.glGenBuffers()GLES30.glBufferData()
    1. 向顶点缓冲对象中写入顶点坐标和纹理坐标数组的数组缓冲GL_ARRAY_BUFFER
    • 方法: GLES30.glBufferData()
    1. 获取顶点坐标和纹理坐标的属性指针并启用
    • 方法:GLES30.glGetAttribLocation()GLES30.glEnableVertexAttribArray()
    1. 按照步长和偏移量解析顶点坐标和纹理坐标,
    • 步长 = (顶点坐标三个点 + 纹理坐标两个点) * Float数据类型字节数为4
    • 偏移量 = 顶点坐标三个点 * Float数据类型字节数为4
    • 方法: GLES30.glVertexAttribPointer()
// 创建VAO, VBO, IBO
fun initVertexBuffer() {// 绑定VAOGLES30.glGenVertexArrays(mVAO.size, mVAO, NO_OFFSET)GLES30.glBindVertexArray(mVAO[0])// 绑定VBO - 只需要一个VBO存储所有数据GLES30.glGenBuffers(mVBO.size, mVBO, NO_OFFSET)GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBO[0])GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexData.size * 4,vertexDataBuffer,GLES30.GL_STATIC_DRAW)// 设置顶点属性指针 - 顶点坐标val positionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition")GLES30.glEnableVertexAttribArray(positionHandle)GLES30.glVertexAttribPointer(positionHandle,VERTEX_POS_DATA_SIZE,GLES30.GL_FLOAT,false,STRIDE,     // 步长,每个顶点5个float (x,y,z,u,v)NO_OFFSET   // 偏移量,位置数据在前)// 设置顶点属性指针 - 纹理坐标val textureHandle = GLES30.glGetAttribLocation(mProgram, "aTexCoord")GLES30.glEnableVertexAttribArray(textureHandle)GLES30.glVertexAttribPointer(textureHandle,TEXTURE_POS_DATA_SIZE,GLES30.GL_FLOAT,false,STRIDE,                          // 步长,每个顶点5个float (x,y,z,u,v)VERTEX_POS_DATA_SIZE * 4         // 偏移量,纹理数据在位置数据之后)// 绑定IBOGLES30.glGenBuffers(mIBO.size, mIBO, NO_OFFSET)// 绑定索引缓冲区数据到IBO[0]GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, mIBO[0])GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,index.size * 2,indexBuffer,GLES30.GL_STATIC_DRAW)// 解绑VAOGLES30.glBindVertexArray(0)// 解绑VBO和IBOGLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)
}

效果图

在这里插入图片描述

相关文章:

Open GL ES ->纹理贴图,顶点坐标和纹理坐标组合到同一个顶点缓冲对象中进行解析

XML文件 <?xml version"1.0" encoding"utf-8"?> <com.example.myapplication.MyGLSurfaceView2 xmlns:android"http://schemas.android.com/apk/res/android"android:id"id/glSurfaceView"android:layout_width"matc…...

题解:AT_arc050_c [ARC050C] LCM 111

一道比较简单的题。&#xff08;我绝对不会告诉你这题我改了很久&#xff09; 题目意思很简单&#xff0c;我就不过多解释了&#xff0c;我们直接进入正题。 题目要我们求 a a a 个 1 1 1 组成的数与 b b b 个 1 1 1 组成的数的最小公倍数除以 m m m 后的余数。先不考虑…...

【408--考研复习笔记】计算机网络----知识点速览

目录 一、计算机网络体系结构 1.计算机网络的定义与功能&#xff1a; 2.网络体系结构相关概念&#xff1a; 3.OSI 七层模型与 TCP/IP 模型&#xff1a; 4.通信方式与交换技术&#xff1a; 电路交换 报文交换 分组交换 5.端到端通信和点到点通信&#xff1a; 6.计算机…...

ISIS报文

IS-IS 报文 目录 IS-IS 报文 一、报文类型与功能 二、报文结构解析 三、核心功能特性 四、典型应用场景 五、抓包数据分析 六、总结 IS-IS&#xff08;中间系统到中间系统&#xff09;协议报文是用于链路状态路由协议中网络设备间交换路由信息的关键载体&#xff0c;其设…...

FPGA——分秒计数器

文章目录 一、实验任务二、系统模块三、工程源码四、管脚信息五、运行结果参考资料总结 一、实验任务 在DE2-115板子上用 Verilog编程实现一个分秒计数器&#xff0c;并具备按键暂停、按键消抖功能。 二、系统模块 分频模块 高频时钟&#xff08;如50MHz&#xff09;分频得到…...

【Java】JVM

一、JVM体系结构 1、虚拟机概述 虚拟机&#xff08;Virtual Machine&#xff09;&#xff1a;一台虚拟的计算机&#xff0c;指一种特殊的软件&#xff0c;他可以在计算机平台和终端用户之间创建一种环境&#xff0c;而终端用户则是基于这个软件所创建的环境来操作软件。虚拟机…...

vue中使用geoscene无法出现弹窗

项目场景&#xff1a; 平日对地图加载使用不复杂的情况下&#xff0c;我通常采用leaflet去加载地图做一些简单的操作。但是最近需要用到arcgis发布的地图服务加载三维场景&#xff0c;于是又用回了geoscene&#xff08;arcgis国产化&#xff09;。这下暴露出很多的问题&#x…...

【Go】数组

数组Array 重点&#xff1a; 数组是值类型 注意点: 1. 数组&#xff1a;是同一种数据类型的固定长度的序列。2. 数组定义&#xff1a;var a [len]int&#xff0c;比如&#xff1a;var a [5]int&#xff0c;数组长度必须是常量&#xff0c;且是类型的组成部分。一旦定义&…...

【运维】Centos硬盘满导致开机时处于加载状态无法开机解决办法

Centos硬盘存储过满导致无法加载 一、准备1.现象2.根因分析3.制定救援方案问题1&#xff1a;无法进入系统确定分析结论 问题2&#xff1a;磁盘数据过多 4.后处理 一、准备 1.现象 Centos虚拟机界面卡顿&#xff0c;随后进行了重启操作&#xff0c;发现重新启动界面一直卡在加…...

JVM——模型分析、回收机制

方法区&#xff1a;存储已被虚拟机加载的类元数据信息(元空间) 堆&#xff1a;存放对象实例&#xff0c;几乎所有的对象实例都在这里分配内存 虚拟机栈&#xff1a;虚拟机栈描述的是|ava方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局…...

kafka 4.x docker启动kafka4.0.0 docker-compose启动最新版kafka 如何使用docker容器启动最新版kafka

1. 镜像选择标签&#xff1a; https://hub.docker.com/r/bitnami/kafka/tags 2. 命令&#xff1a; docker pull bitnami/kafka:4.0.0 3. docker-compose.yml 启动kafka4.0.0&#xff1a; version: 3services:kafka:image: bitnami/kafka:4.0.0container_name: kafkaports:- &…...

BUUCTF-web刷题篇(6)

15.PHP 知识点&#xff1a; ①__wakeup()//将在反序列化之后立即调用&#xff08;当反序列化时变量个数与实际不符是会绕过&#xff09;我们可以通过一个cve来绕过:CVE-2016-7124。将Object中表示数量的字段改成比实际字段大的值即可绕过wakeup函数。条件&#xff1a;PHP5<…...

MySQL篇(一):慢查询定位及索引、B树相关知识详解

MySQL篇&#xff08;一&#xff09;&#xff1a;慢查询定位及索引、B树相关知识详解 MySQL篇&#xff08;一&#xff09;&#xff1a;慢查询定位及索引、B树相关知识详解一、MySQL中慢查询的定位&#xff08;一&#xff09;慢查询日志的开启&#xff08;二&#xff09;慢查询日…...

QT之QML(简单示例)

需求一&#xff1a;点击按钮弹出菜单&#xff0c;并且自定义菜单弹出位置。 mouse.x 和 mouse.y 获取的是相对于 MouseArea&#xff08;在这个例子中是 Button&#xff09;左上角的局部坐标。如果你想要在鼠标点击位置显示 Menu&#xff0c;你需要将这个局部坐标转换为相对于应…...

自动化释放linux服务器内存脚本

脚本说明 使用Linux的Cron定时任务结合Shell脚本来实现自动化的内存释放。 脚本用到sync系统命令 sync的作用&#xff1a;sync 是一个 Linux 系统命令&#xff0c;用于将文件系统缓存中的数据强制写入磁盘。 在你执行reboot、poweroff、shutdown命令时&#xff0c;系统会默认执…...

Linux中的权限管理

一、权限的概念 在 Linux 系统的架构里&#xff0c;权限是构建安全堡垒的基石&#xff0c;精准界定了不同用户对文件与目录的操作边界&#xff0c;对系统安全的维护以及数据完整性的保障起着决定性作用。 1.权限的三种基础类别&#xff1a; 权限对文件的影响对目录的影响 读(r…...

Java对象与JSON字符串的互转

最近&#xff0c;工作中会涉及到Java对象与JSON字符串相互转换&#xff0c;虽然说并不难&#xff0c;但打算还是梳理一番&#xff0c;主要内容有&#xff1a; JSON 字符串 转 普通对象 普通对象 转 JSON 字符串 JSON 字符串数组 转 List 集合对象 List 集合对象 转 JSON 字符串…...

[笔记.AI]向量化

&#xff08;借助 DeepSeek-V3 辅助生成&#xff09; 向量化的定义 向量化&#xff08;Vectorization&#xff09; 是将文本、图像、音频等非结构化数据转换为高维数值向量&#xff08;即一组数字&#xff09;的过程。这些向量能够捕捉数据的语义、特征或上下文信息&#x…...

NSSCTF(MISC)—[justCTF 2020]pdf

相应的做题地址&#xff1a;https://www.nssctf.cn/problem/920 binwalk分离 解压文件2AE59A.zip mutool 得到一张图片 B5F31内容 B5FFD内容 转换成图片 justCTF{BytesAreNotRealWakeUpSheeple}...

Angular的理解

Angular 是一个由 Google 维护的全功能前端框架&#xff0c;适合构建复杂的企业级应用。它采用 TypeScript 作为首选语言&#xff0c;提供了一套完整的解决方案&#xff0c;包括数据绑定、依赖注入、路由、表单处理等。 1. Angular 的核心概念 1.1 组件化架构 Angular 应用由…...

广告推荐算法:COSMO算法与A9算法的对比

COSMO算法与A9算法的概念解析 1. A9算法 定义与背景&#xff1a; A9算法是亚马逊早期为电商平台研发的核心搜索算法&#xff0c;主要用于优化商品搜索结果的排序和推荐&#xff0c;其核心逻辑围绕产品属性与关键词匹配展开。自2003年推出以来&#xff0c;A9通过分析商品标题…...

10. 七大排序(含四种版本快排及优化) ******

排序算法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性主要使用场景直接插入排序O(n)O(n)O(n)O(1)稳定小规模数据或基本有序数据希尔排序O(n^1.3)O(n)O(n log n)O(1)不稳定中等规模数据&#xff0c;对稳定性无要求选择排序O(n)O(n)O(n)O(1)不稳定小规模数…...

以下是C/C++后台开发常见的高概率面试题

一、语言基础 多态的实现 通过虚函数表&#xff08;vtable&#xff09;实现动态绑定&#xff0c;运行时根据对象类型调用对应的函数。虚函数通过virtual关键字声明&#xff0c;子类可重写基类虚函数112。 指针与引用的区别 指针是变量&#xff0c;存储地址&#xff0c;支持多…...

CentOS-查询实时报错日志-查询前1天业务报错gz压缩日志

最新版本更新 https://code.jiangjiesheng.cn/article/364?from=csdn 推荐 《高并发 & 微服务 & 性能调优实战案例100讲 源码下载》 1. 查询实时报错日志 物理路径(带*的放在靠后,或者不用*) cd /home/logs/java-gz-log-dir && tail -2000f java-gz-l…...

破界·共生:生成式人工智能(GAI)认证重构普通人的AI进化图谱

在当今这个科技日新月异的时代,人工智能(AI)正以惊人的速度改变着我们的世界。从智能家居到自动驾驶,从医疗诊断到金融分析,AI的应用已经渗透到社会生活的方方面面。面对如此迅猛的发展态势,我们不禁要问:人工智能的未来将走向何方?普通人又该如何把握这一历史机遇,学…...

HTTP代理:网页加速的隐形引擎

目录 引言&#xff1a;网页加载速度为何至关重要&#xff1f; 一、HTTP代理的核心加速原理 二、四大加速黑科技详解 三、实战场景性能对比 四、代理加速的隐藏代价 五、未来发展趋势 结语&#xff1a;智能代理的选型指南 引言&#xff1a;网页加载速度为何至关重要&#…...

Unity 常见报错 定位和查找方法

1.控制台 直接看报错信息 2.打log 例子&#xff1a; for(int i 0;i < 8;i) {Debug.Log(i);//这是打的log,看看到底i是几的时候出问题gameObject.name strs[i];} 3.断点调试 &#xff08;1&#xff09;在你想打断点的行&#xff0c;左边空白处点击可以打断点&#xff…...

人工智能之数学基础:初等反射阵

本文重点 在线性代数中,初等反射阵(Householder矩阵)作为一类特殊的正交矩阵,在矩阵变换、特征值计算及几何变换等领域具有广泛应用。其简洁的构造方式和丰富的数学性质,使其成为数值分析和几何处理中的重要工具。 什么是初等反射阵(豪斯霍尔德变换) I为单位矩阵,wwT…...

《Linux运维总结:基于银河麒麟V10操作系统+ARM64架构CPU二进制部署单机ACL版consul v1.18.1》

总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:《Linux运维篇:Linux系统运维指南》 一、简介 1、什么是consul Consul是HashiCorp公司推出的开源工具,用于实现 分布式系统的服务发现与配置。 Consul是分布式的、高可用的、可横向扩展的。 架构图…...

web网站页面测试点---添加功能测试

添加 一、创建新的申请时&#xff0c;关闭网络查看数据是否存在&#xff0c;并提示网络错位相关提示语 二、在文本框内输入数据 1.在文本框内输入空格&#xff0c;查看文本内容前后是否存在空格 2.在文本框内输入最大长度&#xff0c;查看能否正确提交 3.在文本框内输入最大长…...

实操自动生成接口自动化测试用例

​这期抽出来的问题是关于如何使用Eolinker自动生成接口自动化测试用例&#xff0c;也就是将API文档变更同步到测试用例&#xff0c;下面是流程的示例解析。 导入并关联API文档和自动化测试用例 首先是登陆Eolinker&#xff0c;可以直接在线使用。 进入流程测试用例详情页&am…...

【华为OD技术面试真题 - 技术面】- Java面试题(17)

华为OD面试真题精选 专栏:华为OD面试真题精选 目录: 2024华为OD面试手撕代码真题目录以及八股文真题目录 文章目录 华为OD面试真题精选虚拟机分区1. **虚拟磁盘分区**2. **虚拟机的内存分区**3. **CPU分配**4. **虚拟网络分区**5. **存储虚拟化和分区**6. **虚拟机分区管理**…...

mapState 函数的用法

mapState 是 Vuex 提供的一个辅助函数&#xff0c;其主要作用是将 Vuex 仓库中的状态映射到组件的计算属性中&#xff0c;这样在组件里就能像访问本地计算属性一样访问 Vuex 仓库中的状态。以下为你详细介绍 mapState 函数的不同用法。 1. 基本用法&#xff1a;对象形式 当使…...

【学Rust写CAD】17 通用2D仿射变换矩阵结构体(matrix/generic.rs)

源代码 // matrix.rs use std::ops::{Add, Mul};use std::ops::{Add, Mul};/// 通用2D仿射变换矩阵&#xff08;元素仅需Copy&#xff09; #[derive(Clone, Copy, Debug, PartialEq)] pub struct Matrix<X, Y, Xx, Xy, Yx, Yy> {pub x: X, pub y: Y,pub xx: Xx, pub xy:…...

STM32单片机入门学习——第3-4节: [2-1、2]软件安装和新建工程

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.01 STM32开发板学习——第一节&#xff1a; [1-1]课程简介 前言开发板说明引用解答和…...

Linux详解

01 计算机组成原理 1、什么是计算机&#xff1f; 计算机俗称电脑&#xff0c;就相当于一种人造人&#xff0c; 电脑二字蕴含着人类的对计算机的终极期望&#xff0c;希望一通电就能够像人脑一样去工作 2、为何要有计算机? 为了造出一种机器来取代人去工作&…...

IP数据报报文格式

一 概述 IP数据报由两部分组成&#xff1a;首部数据部分。首部的前一部分是固定长度&#xff0c;一共20字节大小&#xff0c;是所有IP数据报文必须具有的&#xff1b;固定部分后面是一些可选字段&#xff0c;其长度是可变的。 二 首部固定部分各字段意义 &#xff08;1&…...

自然语言处理(25:(终章Attention 1.)Attention的结构​)

系列文章目录 终章 1&#xff1a;Attention的结构 终章 2&#xff1a;带Attention的seq2seq的实现 终章 3&#xff1a;Attention的评价 终章 4&#xff1a;关于Attention的其他话题 终章 5&#xff1a;Attention的应用 目录 系列文章目录 前言 Attention的结构 一.seq…...

Minimind 训练一个自己专属语言模型

发现了一个宝藏项目&#xff0c; 宣传是完全从0开始&#xff0c;仅用3块钱成本 2小时&#xff01;即可训练出仅为25.8M的超小语言模型MiniMind&#xff0c;最小版本体积是 GPT-3 的 17000&#xff0c;做到最普通的个人GPU也可快速训练 https://github.com/jingyaogong/minimi…...

Android里面内存优化

核心思路 在Android开发中&#xff0c;内存优化是保证应用性能稳定和用户体验的关键。我通常从以下几个方面进行内存优化&#xff1a; 1. 内存泄漏检测与修复 使用LeakCanary等工具检测内存泄漏 常见内存泄漏场景&#xff1a; 静态变量持有Activity/Fragment引用 非静态内部…...

Git操作指南

Git操作指南 1.安装并配置Git Git官网&#xff1a;https://git-scm.com/downloads 安装完成后&#xff0c;打开Git Bash&#xff0c;配置Git&#xff1a; git config --global user.email "emailexample.com" git config --global user.name "Your Name&quo…...

【蓝桥杯—单片机】通信总线专项 | 真题整理、解析与拓展 (更新ing...)

通信总线专项 前言SPI第十五届省赛题 UART/RS485/RS232UARTRS485RS232第十三届省赛题小结和拓展&#xff1a;传输方式的分类第十三届省赛 其他相关考点网络传输速率第十五届省赛题第十二届省赛题 前言 在本文中我会把 蓝桥杯单片机赛道 历年真题 中涉及到通信总线的题目整理出…...

深入探究C语言中的二进制世界:从原理到实践

文章目录 深入探究C语言中的二进制世界&#xff1a;从原理到实践一、进制的本质与C语言实现1. 进制系统全景2. C语言中的进制表示3. 格式化输出进阶 二、进制转换的工程实践1. 转换算法实现2. 实际应用中的转换技巧快速二进制 - 十六进制转换位运算优化转换 3. 进制转换详细示例…...

【android bluetooth 协议分析 13】【RFCOMM详解 2】【通俗易懂 rfcomm 基本流程】

RFCOMM 协议 基本流程 一、连接建立流程&#xff08;附 BTsnoop 实例解析&#xff09; 1. L2CAP 通道建立 BTsnoop 表现&#xff1a; L2CAP_Connection_Request (PSM0x0003) // 请求建立RFCOMM专用通道L2CAP_Connection_Response (Success) // 对方同意作用&#xff1a;相…...

万字知识篇(2):SpringBoot的常用注解(上)

SpringBoot的常用注解非常的多&#xff0c;一篇文章根本讲不完&#xff0c;将分为上下两章&#xff0c;通过本章你将会系统的学习到&#xff1a; 1. 注解在SpringBoot中的作用 2. SpringBoot 常用注解速查表 3. 核心启动类注解 4. Configuration 5. Bean 6. PropertySource 7. …...

Postman —— postman实现参数化

什么时候会用到参数化 比如&#xff1a;一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块&#xff1a;正确的用户名&#xff0c;密码 成功&#xff1b;错误的用户名&#xff0c;正确的密码 失败 postman实现参数化 在实际的接口测试中&#xff0c;部分参数每…...

Docker学习--容器生命周期管理相关命令--docker create 命令

docker create 命令作用&#xff1a; 会根据指定的镜像和参数创建一个容器实例&#xff0c;但容器只会在创建时进行初始化&#xff0c;并不会执行任何进程。 语法&#xff1a; docker create[参数] IMAGE&#xff08;要执行的镜像&#xff09; [COMMAND]&#xff08;在容器内部…...

算法基础_基础算法【高精度 + 前缀和 + 差分 + 双指针】

算法基础_基础算法【高精度 前缀和 差分 双指针】 ---------------高精度---------------791.高精度加法题目介绍方法一&#xff1a;代码片段解释片段一&#xff1a; 解题思路分析 792. 高精度减法题目介绍方法一&#xff1a;代码片段解释片段一&#xff1a; 解题思路分析 7…...

C语言深度解析:从零到系统级开发的完整指南

一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性&#xff0c;成为系统级开发的首选语言。例如&#xff0c;Linux内核通过C语言直接操作内存和硬件寄存器&#xff0c;实现高效进程调度。 关键点&#xff1a; malloc/free直接管理内存&#…...

Axure疑难杂症:完美解决中继器筛选问题(时间条件筛选、任性筛选)

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;中继器筛选专题 主要内容&#xff1a;时间条件筛选、多条件组合筛选、多个单一条件混合筛选 应用场景&#xff1a;各类数据表的多条件筛选均可使用…...