WebGL进阶(十一)层次模型

news2024/11/24 18:20:58

理论基础:

效果:

源码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入gl-matrix.js库,用于 WebGL 中的矩阵运算 -->
    <script src="gl-matrix.js"></script>
    <script>
        // 顶点着色器程序
        let vertexstring = `
        attribute vec4 a_position; // 顶点位置属性
        uniform mat4 u_formMatrix; // 变换矩阵
        attribute vec4 a_Normal; // 顶点法线属性
        uniform vec3 u_PointLightPosition; // 点光源位置
        uniform vec3 u_DiffuseLight; // 散射光颜色
        uniform vec3 u_AmbientLight; // 环境光颜色
        varying vec4 v_Color; // 传递给片段着色器的颜色
        void main(void){
            gl_Position = u_formMatrix * a_position; // 应用变换矩阵
            vec3 normal = normalize(a_Normal.xyz); // 法线归一化
            vec3 lightDirection = normalize(u_PointLightPosition - vec3(gl_Position.xyz)); // 计算光源方向
            float nDotL = max(dot(lightDirection, normal), 0.0); // 计算法线和光源方向的点积
            vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0)* nDotL; // 计算散射光
            vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0); // 计算环境光
            v_Color = vec4(diffuse + ambient, 1); // 结合散射光和环境光
        }
        `;
        // 片段着色器程序
        let fragmentstring = `
        precision mediump float; // 精度声明
        varying vec4 v_Color; // 从顶点着色器接收的颜色
        void main(void){
          gl_FragColor =v_Color; // 设置片断颜色
        }
        `;

        // WebGL上下文和一些变量的声明
        var webgl;
        var angle = 45;
        var webglDiv;
        var indices;
        var g_joint1Angle = 0.0;
        var ANGLE_STEP = 3.0;
        var g_arm1Angle = -90.0;

        // 初始化函数,设置WebGL环境
        function init() {
            // 初始化WebGL
            initWebgl();
            // 初始化着色器
            initShader();
            // 初始化数据
            initBuffer();
            // 初始化事件
            initEvent();
            // 清空画板
            clearn();
            // 创建光源
            initLight();
            // 绘制图形
            draw();
        }

        // 初始化WebGL上下文
        function initWebgl() {
            webglDiv = document.getElementById('myCanvas');
            webgl = webglDiv.getContext("webgl");
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);
        }

        // 初始化着色器
        function initShader() {
            // 创建顶点着色器和片段着色器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 设置着色器源码
            webgl.shaderSource(vsshader, vertexstring);
            webgl.shaderSource(fsshader, fragmentstring);

            // 编译着色器
            webgl.compileShader(vsshader);
            webgl.compileShader(fsshader);
            // 检查着色器编译状态
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }
            // 创建程序并附加着色器
            let program = webgl.createProgram();
            webgl.attachShader(program, vsshader);
            webgl.attachShader(program, fsshader)
            webgl.linkProgram(program);
            webgl.useProgram(program);
            webgl.program = program;
        }

        // 清空画板并设置背景色和深度测试
        function clearn() {
            webgl.clearColor(0, 0, 0, 1);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.enable(webgl.DEPTH_TEST);
        }

        // 初始化变换矩阵
        function initTransformation(angele, rotateArr, ModelMatrix = glMatrix.mat4.create()) {
            let ProjMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ProjMatrix);
            glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000); // 设置透视投影

            let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

            glMatrix.mat4.rotate(ModelMatrix, ModelMatrix, degreesToRads(angele), rotateArr); // 旋转模型矩阵
            let ViewMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ViewMatrix);
            glMatrix.mat4.lookAt(ViewMatrix, [50, 50, 50], [0, 0, 0], [0, 1, 0]); // 设置视图矩阵

            let mvMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvMatrix);
            glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrix); // 计算模型视图矩阵

            let mvpMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvpMatrix);
            glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix); // 计算模型视图投影矩阵
            webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix);
            return ModelMatrix;
        }

        // 初始化事件监听
        function initEvent() {
            document.onkeydown = keydown;
        }

        // 初始化光源
        function initLight() {
            let u_DiffuseLight = webgl.getUniformLocation(webgl.program, 'u_DiffuseLight');
            webgl.uniform3f(u_DiffuseLight, 1.0, 1.0, 1.0); // 设置散射光颜色
            let u_LightDirection = webgl.getUniformLocation(webgl.program, 'u_PointLightPosition');
            webgl.uniform3fv(u_LightDirection, [3.0, 3.0, 4.0]); // 设置点光源位置
            let u_AmbientLight = webgl.getUniformLocation(webgl.program, 'u_AmbientLight');
            webgl.uniform3f(u_AmbientLight, 0.8, 0.8, 0.8); // 设置环境光颜色
        }

        // 初始化缓冲区
        function initBuffer() {
            // 顶点数据
            var vertices = new Float32Array([
                // 顶点坐标
            ]);

            // 法线数据
            var normals = new Float32Array([
                // 法线坐标
            ]);

            // 顶点索引
            indices = new Uint8Array([
                // 顶点索引
            ]);

            // 创建顶点位置缓冲区
            let pointPosition = new Float32Array(vertices);
            let aPsotion = webgl.getAttribLocation(webgl.program, "a_position");
            let triangleBuffer = webgl.createBuffer();
            webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aPsotion);
            webgl.vertexAttribPointer(aPsotion, 3, webgl.FLOAT, false, 0, 0);

            // 创建法线缓冲区
            let aNormal = webgl.getAttribLocation(webgl.program, "a_Normal");
            let normalsBuffer = webgl.createBuffer();
            let normalsArr = new Float32Array(normals);
            webgl.bindBuffer(webgl.ARRAY_BUFFER, normalsBuffer);
            webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, normalsArr, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aNormal);
            webgl.vertexAttribPointer(aNormal, 3, webgl.FLOAT, false, 0, 0);

            // 创建索引缓冲区
            let indexBuffer = webgl.createBuffer();
            let indices1 = new Uint8Array(indices);
            webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer);
            webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, indices1, webgl.STATIC_DRAW);
        }

        // 按键事件处理函数
        function keydown(ev) {
            switch (ev.keyCode) {
                // 按键事件,控制关节角度
            }
            clearn()
            draw();
        }
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入gl-matrix.js库,用于 WebGL 中的矩阵运算 -->
    <script src="gl-matrix.js"></script>
    <script>
        // 顶点着色器程序
        let vertexstring = `
        attribute vec4 a_position; // 顶点位置属性
        uniform mat4 u_formMatrix; // 变换矩阵
        attribute vec4 a_Normal; // 顶点法线属性
        uniform vec3 u_PointLightPosition; // 点光源位置
        uniform vec3 u_DiffuseLight; // 散射光颜色
        uniform vec3 u_AmbientLight; // 环境光颜色
        varying vec4 v_Color; // 传递给片段着色器的颜色
        void main(void){
            gl_Position = u_formMatrix * a_position; // 应用变换矩阵
            vec3 normal = normalize(a_Normal.xyz); // 法线归一化
            vec3 lightDirection = normalize(u_PointLightPosition - vec3(gl_Position.xyz)); // 计算光源方向
            float nDotL = max(dot(lightDirection, normal), 0.0); // 计算法线和光源方向的点积
            vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0)* nDotL; // 计算散射光
            vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0); // 计算环境光
            v_Color = vec4(diffuse + ambient, 1); // 结合散射光和环境光
        }
        `;
        // 片段着色器程序
        let fragmentstring = `
        precision mediump float; // 精度声明
        varying vec4 v_Color; // 从顶点着色器接收的颜色
        void main(void){
            gl_FragColor = v_Color; // 设置片断颜色
        }
        `;

        // WebGL上下文和一些变量的声明
        var webgl;
        var angle = 45;
        var webglDiv;
        var indices;
        // 各个关节的角度变量
        var g_joint1Angle = 86.0;
        var ANGLE_STEP = 3.0;
        var g_arm1Angle = 160.0;
        var g_palm1Angle = 0.0;
        var g_finger1Angle = 0.0;
        var g_chest1Angle = 0;

        // 初始化函数,设置WebGL环境
        function init() {
            // 初始化WebGL
            initWebgl();
            // 初始化着色器
            initShader();
            // 清空画板
            clearn();
            // 创建光源
            initLight();
            // 绘制头部
            drawHead()
            // 初始化数据
            initBuffer();
            // 初始化事件
            initEvent();
            // 绘制图形
            let drawMatrix = chestDraw();
            let drawMatrixCopy = drawMatrix.slice(0);
            drawLeft(drawMatrix);
            drawRight(drawMatrixCopy);
        }

        // 初始化WebGL上下文
        function initWebgl() {
            webglDiv = document.getElementById('myCanvas');
            webgl = webglDiv.getContext("webgl");
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);
        }

        // 初始化着色器
        function initShader() {
            // 创建顶点着色器和片段着色器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 设置着色器源码
            webgl.shaderSource(vsshader, vertexstring);
            webgl.shaderSource(fsshader, fragmentstring);

            // 编译着色器
            webgl.compileShader(vsshader);
            webgl.compileShader(fsshader);
            // 检查着色器编译状态
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }
            // 创建程序并附加着色器
            let program = webgl.createProgram();
            webgl.attachShader(program, vsshader);
            webgl.attachShader(program, fsshader);
            webgl.linkProgram(program);
            webgl.useProgram(program);
            webgl.program = program;
        }

        // 清空画板并设置背景色和深度测试
        function clearn() {
            webgl.clearColor(0, 0, 0, 1);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.enable(webgl.DEPTH_TEST);
        }

        // 初始化变换矩阵
        function initTransformation(angle, rotateArr, ModelMatrix = glMatrix.mat4.create()) {
            let ProjMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ProjMatrix);
            glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000); // 设置透视投影

            let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

            glMatrix.mat4.rotate(ModelMatrix, ModelMatrix, degreesToRads(angle), rotateArr);
            let ViewMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ViewMatrix);
            glMatrix.mat4.lookAt(ViewMatrix, [0, 0, 100], [0, 0, 0], [0, 1, 0]); // 设置视图矩阵

            let mvMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvMatrix);
            glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrix); // 计算模型视图矩阵

            let mvpMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvpMatrix);
            glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix); // 计算模型视图投影矩阵
            webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix);
            return ModelMatrix;
        }

        // 初始化事件监听
        function initEvent() {
            document.onkeydown = keydown;
        }

        // 初始化光源
        function initLight() {
            let u_DiffuseLight = webgl.getUniformLocation(webgl.program, 'u_DiffuseLight');
            webgl.uniform3f(u_DiffuseLight, 1.0, 1.0, 1.0); // 设置散射光颜色
            let u_LightDirection = webgl.getUniformLocation(webgl.program, 'u_PointLightPosition');
            webgl.uniform3fv(u_LightDirection, [3.0, 3.0, 4.0]); // 设置点光源位置
            let u_AmbientLight = webgl.getUniformLocation(webgl.program, 'u_AmbientLight');
            webgl.uniform3f(u_AmbientLight, 0.8, 0.8, 0.8); // 设置环境光颜色
        }

        // 初始化缓冲区
        function initBuffer() {
            // 顶点数据
            var vertices = new Float32Array([
                // 顶点坐标
            ]);

            // 法线数据
            var normals = new Float32Array([
                // 法线坐标
            ]);

            // 顶点索引
            indices = new Uint8Array([
                // 顶点索引
            ]);

            // 创建顶点位置缓冲区
            let pointPosition = new Float32Array(vertices);
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position");
            let triangleBuffer = webgl.createBuffer();
            webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aPosition);
            webgl.vertexAttribPointer(aPosition, 3, webgl.FLOAT, false, 0, 0);

            // 创建法线缓冲区
            let aNormal = webgl.getAttribLocation(webgl.program, "a_Normal");
            let normalsBuffer = webgl.createBuffer();
            let normalsArr = new Float32Array(normals);
            webgl.bindBuffer(webgl.ARRAY_BUFFER, normalsBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, normalsArr, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aNormal);
            webgl.vertexAttribPointer(aNormal, 3, webgl.FLOAT, false, 0, 0);

            // 创建索引缓冲区
            let indexBuffer = webgl.createBuffer();
            let indices1 = new Uint8Array(indices);
            webgl.bindBuffer(web
void gl.drawElements(mode, count, type, offset);

 

复盘:

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

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

相关文章

vscode下面python调试报错ImportError: cannot import name ‘Literal‘ from ‘typing‘

1 问题描述 我在vscode下面编写python程序&#xff0c;这个程序是在一个英伟达anoconda环境下的项目。之前能运行能调试&#xff0c;最近发现只能运行ctlf5&#xff0c;但是使用f5进行调试时&#xff0c;报错“File “c:\Users\86137.vscode\extensions\ms-python.debugpy-202…

(免费送源码)计算机毕业设计原创定制:Java+JSP+HTML+JQUERY+AJAX+MySQL springboot计算机类专业考研学习网站管理系统

摘 要 大数据时代下&#xff0c;数据呈爆炸式地增长。为了迎合信息化时代的潮流和信息化安全的要求&#xff0c;利用互联网服务于其他行业&#xff0c;促进生产&#xff0c;已经是成为一种势不可挡的趋势。在大学生在线计算机类专业考研学习网站管理的要求下&#xff0c;开发一…

Android 常用命令和工具解析之GPU相关

目录 1、GPU基本信息 1.1 获取GPU基本信息 1.2 伪造GPU基本信息 2、GPU内存信息 3、经典案例 案例1&#xff1a;GPU伪造信息方案 案例2&#xff1a;GPU内存统计算法 GPU 指的是 Graphics Processing Unit&#xff0c;即图形处理单元。GPU 是一种专门用于处理图形和图像相…

day03(单片机高级)RTOS

目录 RTOS(实时操作系统) 裸机开发模式 轮询方式 前后台&#xff08;中断方式&#xff09; 改进&#xff08;前后台&#xff08;中断&#xff09;&#xff09;定时器 裸机进一步优化 裸机的其他问题 RTOS的概念 什么是RTOS 为什么要使用 RTOS RTOS的应用场景 RTOS的…

cookie反爬----普通服务器,阿里系

目录 一.常见COOKIE反爬 普通&#xff1a; 1. 简介 2. 加密原理 二.实战案例 1. 服务器响应cookie信息 1. 逆向目标 2. 逆向分析 2. 阿里系cookie逆向 1. 逆向目标 2. 逆向分析 实战&#xff1a; 无限debugger原理 1. Function("debugger").call() 2. …

C++中的erase()函数用法总结

在 C 中&#xff0c;erase() 是 std::string 和 std::vector 等容器中的成员函数&#xff0c;用于删除容器中的元素。erase可以删去容器中指定位置的元素&#xff0c;容器的size&#xff08;大小&#xff09;会改变&#xff0c;但是容器的容量不变。 常用用法&#xff1a; 1.…

全面解析:HTML页面的加载全过程(四)--浏览器渲染之样式计算

主线程遍历得到的 DOM 树&#xff0c;依次为树中的每个节点计算出它最终的样式&#xff0c;称之为 Computed Style。 通过前面生成的DOM 树和 CSSOM 树&#xff0c;遍历 DOM 树&#xff0c;为每一个 DOM 节点&#xff0c;计算它的所有 CSS 属性&#xff0c;最后会得到一棵带有…

Linux|内存级文件原理

目录 进程与文件 Linux下的文件系统 文件操作&#xff0c;及文件流 C语言函数 文件流 文件描述符 系统调用操作 系统调用参数 重定向与文件描述符 输出重定向 输入重定向 文件内容属性 Linux下一切皆文件 进程与文件 当我们对文件进行操作时&#xff0c;文件必须…

40分钟学 Go 语言高并发:Context包与并发控制

Context包与并发控制 学习目标 知识点掌握程度应用场景context原理深入理解实现机制并发控制和请求链路追踪超时控制掌握超时设置和处理API请求超时、任务限时控制取消信号传播理解取消机制和传播链优雅退出、资源释放context最佳实践掌握使用规范和技巧工程实践中的常见场景…

【SpringMVC - 1】基本介绍+快速入门+图文解析SpringMVC执行流程

目录 1.Spring MVC的基本介绍 2.大致分析SpringMVC工作流程 3.SpringMVC的快速入门 首先大家先自行配置一个Tomcat 文件的配置 配置 WEB-INF/web.xml 创建web/login.jsp 创建com.ygd.web.UserServlet控制类 创建src下的applicationContext.xml文件 重点的注意事项和说明…

neo4j图数据库community-5.50创建多个数据库————————————————

1.找到neo4J中的conf文件&#xff0c;我的路径是&#xff1a;D:\Program Files\neo4j-community-5.5.0-windows\neo4j-community-5.5.0\conf 这里找自己的安装路径&#xff0c; 2.用管理员模式打开conf文件&#xff0c;右键管理员&#xff0c;记事本或者not 3.选中的一行新建一…

如何最简单、通俗地理解Python的迭代器?

我们知道迭代器&#xff08;iterator&#xff09;可以用for循环去取数&#xff0c;这和列表取数有什么区别呢&#xff1f; 想理解Python迭起器的差异&#xff0c;有个很简单的例子 打个比方&#xff0c;你去玩街头投篮机&#xff0c;可以投5个球&#xff0c;这里有两种方式&a…

JavaEE 【知识改变命运】02 多线程(1)

文章目录 线程是什么&#xff1f;1.1概念1.1.1 线程是什么&#xff1f;1.1.2 为什么要有线程1.1.3 进程和线程的区别1.1.4 思考&#xff1a;执行一个任务&#xff0c;是不是创建的线程或者越多是不是越好&#xff1f;&#xff08;比如吃包子比赛&#xff09;1.1.5 ) Java 的线程…

Linux内核USB2.0驱动框架分析--USB包

一&#xff0c; 包的组成 每个包都由SOP&#xff08;包起始域&#xff09;、SYNC&#xff08;同步域&#xff09;、Packet Content&#xff08;包内容&#xff09;、EOP&#xff08;包结束域&#xff09;四部分组成&#xff0c;其中SOP、SYNC、EOP为所有包共有的域&#xff0c…

云轴科技ZStack亮相2024 IDC中国生态峰会,共塑AI时代IT生态新格局

11月21日&#xff0c;2024 IDC中国生态峰会在北京举办&#xff0c;吸引了超过300位生态伙伴齐聚一堂&#xff0c;聚焦行业内最前沿的热点话题。本届峰会以“创见先机&#xff0c;智领风云”为主题&#xff0c;深入探讨宏观经济趋势、技术革新以及如何融合AI与数据技术&#xff…

C0029.在Clion中解决Debug时,提示Process finished with exit code -1的错误

1.错误提示 Process finished with exit code -12.解决办法 如上在使用Debug进行代码调试时&#xff0c;直接出现如上报错&#xff0c;解决办法就是直接点击运行程序&#xff0c;即可查出报错编号&#xff0c;然后根据报错编号来查找问题&#xff1b; 然后在网上就可以根据该…

07-Making a Bar Chart with D3.js and SVG

课程链接 Curran的课程&#xff0c;通过 D3.js 的 scaleLinear, max, scaleBand, axisLeft, axisBottom&#xff0c;根据 .csv 文件生成一个横向柱状图。 【注】如果想造csv数据&#xff0c;可以使用通义千问&#xff0c;关于LinearScale与BandScale不懂的地方也可以在通义千…

读取各种来源格式单细胞数据集构建seurat分析对象,代做生信分析

参考资料和分析注意事项 全流程的分析指导视频 演示数据集网盘文件 分析参数文件路径格式的特别提示 大家给要分析用到的文件路径或目录路径的时候&#xff0c;以D:/omics_tools/demo_data/scrnaseq/GSE189125/GSE189125_5prime_scRNAseq_seqbatchA_counts.txt.gz 这个文件为…

SQL-多表操作

前文所介绍的sql操作都是基于单表进行的&#xff0c;接下来我们来学习多表操作。 多表设计 在实际的项目开发中&#xff0c;会根据业务需求和业务模块之间的关系进行数据库表结构设计&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xf…

c++ STL线程安全使用

c STL不是线程安全的&#xff0c;因此在多线程中使用的时候&#xff0c;操作同一个容器&#xff0c;会崩溃&#xff0c;因此需要解决线程安全的问题&#xff1a; 使用实例类似于以下&#xff1a; #include <thread> #include <vector> #include "thread_safe…