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

LearnOpenGL-入门-8.坐标系统

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正

我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject

LearnOpenGL中文官网:https://learnopengl-cn.github.io/

文章目录

  • 坐标系统
    • 概述
    • 局部空间
    • 世界空间
    • 观察空间
    • 裁剪空间
      • 正交投影
      • 透视投影
    • 把他们组合到一起
  • 进入3D
    • 例子1
    • 例子2:更加3D
    • 例子3:箱子派对

坐标系统

  • 标准化设备坐标介绍

    • 每个顶点的xyz坐标都在**-1.01.0**之间

    • OpenGL希望在每次顶点着色器运行后,我们可见的所有顶点都为标准化设备坐标

    • 我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将这些坐标变换为标准化设备坐标

    • 将标准化设备坐标传入光栅器(Rasterizer),将它们变换为屏幕上的二维坐标或像素。

  • 多个坐标系统

    • 为什么存在

      坐标变换为标准化设备坐标,接着再转化为屏幕坐标的过程通常是分步进行的,所以物体的顶点在最终转化为屏幕坐标之前还会被变换到多个坐标系统

    • 多个坐标系统的优点优点

      在这些特定的坐标系统中,一些操作或运算更加方便和容易

概述

  1. 局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标
  2. 局部坐标通过Model矩阵变换为世界空间坐标,这些坐标相对于世界的全局原点,它们会和其它物体一起相对于世界的原点进行摆放。
  3. 观察空间坐标,通过view矩阵将世界空间转换到观察空间,使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
  4. 裁剪坐标,通过投影矩阵从观察空间到裁剪空间,裁剪坐标会被处理(透视除法)至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
  5. 视口变换将-1.0到1.0范围的裁剪坐标(标准化设备坐标)变换到由glViewport函数所定义的坐标范围内。

局部空间

  • 简介

    局部空间是指物体所在的坐标空间

世界空间

  • 简介

    是指顶点相对于(游戏)世界的坐标

  • 如何从局部到世界坐标

    该变换是由模型矩阵(Model Matrix)实现的。

观察空间

  • 简介

    摄像机的视角所观察到的空间,是由观察矩阵(Model Matrix)从世界到观察坐标。

  • view(观察)矩阵

    由一系列的位移和旋转的组合来完成,平移/旋转场景从而使得特定的对象被变换到摄像机的前方。

    这些组合在一起的变换通常存储在一个观察矩阵(View Matrix)里

裁剪空间

  • 简介

    • OpenGL自动执行
    • 范围内的保留,范围外的裁掉
    • 当裁剪后剩下的可见的片段就是裁剪空间
  • 如何进入裁剪空间

    投影矩阵将观察空间变换到裁剪空间

  • 投影矩阵分为

    • 正交投影
    • 透视投影
  • 透视除法

    • 什么时候执行

      一旦所有顶点被变换到裁剪空间,OpenGL自动会透视除法(在每一个顶点着色器运行的最后被自动执行)

    • 它如何做

      将位置向量的x,y,z分量分别除以向量的齐次w分量

    • 结果

      透视除法执行后才将裁剪坐标系变换到标准化设备坐标系

  • 小结工作流程(自己捋的,很大概率有误)

    设置-1000到1000范围,投影矩阵会将在这个范围内的坐标从观察空间变换到裁剪空间,然后OpenGL自动执行透视除法,转换为标准化设备坐标的范围(-1.0, 1.0)。

    所有的坐标先转换为(-1, 1)之间,然后不在-1.0到1.0的范围,会被裁剪掉(OpenGL自动执行裁剪)。

  • 在标准化设备坐标系之后

    执行第一张图所说的视口变换

    最终的坐标(标准化设备坐标系)将会被映射到屏幕空间中(使用glViewport中的设定),并被变换成片段。

    即:视口变换将标准化设备坐标系到屏幕坐标

正交投影

  • 图示

  • glm创建

    glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
    
    • 前两个参数指定了平截头体的左右坐标

    • 第三和第四参数指定了平截头体的底部和顶部

      通过这四个参数我们定义了近平面和远平面的大小

    • 第五和第六个参数则定义了近平面和远平面的距离

  • 缺点

    这个投影没有将透视(Perspective)考虑进去,所有的物体仿佛都保持原有大小。

    因为这个投影不改变每个向量的w分量,都保持1,透视除法是用x,y,z除以w分量,w=1,自然不会变。

透视投影

  • 图示

  • 简介

    近大远小

  • 透视投影矩阵如何工作

    • 这个投影矩阵将给定的平截头体范围映射到裁剪空间

    • 除此之外还修改了每个顶点坐标的w

      • 从而使得离观察者越远的顶点坐标w分量越大。

      • 透视除法所做

        将位置向量的x,y,z分量分别除以向量的齐次w分量,因为远的顶点坐标w分量大,所以距离观察者越远顶点坐标就会越小

    • 什么时候执行透视除法

      • 上面有讲:由projection投影矩阵变换到裁剪空间后
      • OpenGL要求所有可见的坐标都落在-1.0到1.0范围内,作为顶点着色器最后的输出。因此,一旦坐标在裁剪空间内之后,就会在裁剪空间坐标上执行透视除法,透视除法执行后便是标准化设备坐标(-1.0,1.0)范围。
  • glm创建

    glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
    
    • 第一个参数定义了fov的值,它表示的是视野

    • 第二个参数设置了宽高比,由视口的宽除以高所得

    • 第三和第四个参数设置了平截头体的平面

      • 说明第三个参数

        near 值设置太大时(如10.0f),OpenGL会将靠近摄像机的坐标**(在0.0f和10.0f之间)**都裁剪掉

  • 透视投影与正交投影对比

把他们组合到一起

  • 注意顺序

    • 写代码顺序

      v = projection * view * model * local

    • 读顺序

      需从右往左阅读矩阵

  • 再重复了一次裁剪空间这点的内容

    OpenGL将会自动进行透视除法和裁剪操作

    重要的顺序

    • 顶点着色器的输出要求所有的顶点都在裁剪空间内,这正是我们刚才使用变换矩阵所做的。
    • OpenGL然后对裁剪坐标自动执行透视除法从而将它们变换到标准化设备坐标
    • 视口变换:OpenGL会使用glViewPort内部的参数来将标准化设备坐标映射到屏幕坐标

进入3D

  • 观察矩阵
    • 将摄像机向后移动,和将整个场景向前移动是一样的。
    • 这正是观察矩阵所做的,我们以相反于摄像机移动的方向移动整个场景
    • 因为我们想要往后移动,所以场景需要沿着z轴负方向平移来实现,它会给我们一种我们在往后移动的感觉。(opengl右手坐标系)

例子1

  • 代码

    glsl

    顶点着色器

    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec2 aTexCoord;
    out vec2 TexCoord;
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    void main()
    {// 注意乘法要从右向左读gl_Position = projection * view * model * vec4(aPos, 1.0);TexCoord = aTexCoord;
    }
    
    • 在顶点着色器上进行坐标系转换,从局部空间到裁剪空间

      • 代码顺序是

        project*view*model*local

      • 解读顺序是

        相反的需从右往左读:将顶点local经过model矩阵到世界空间,再经过view矩阵到观察空间,再经过project到裁剪空间。

    • 再次重复

      到裁剪空间后,经过透视除法到标准化设备坐标系,再经过视口变换到屏幕坐标,这两个是opengl自动执行的

    片段着色器

    #version 330 core
    out vec4 FragColor;
    in vec2 TexCoord;
    uniform sampler2D texture1;
    uniform sampler2D texture2;
    void main()
    {FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
    }
    

    cpp

    Shader ourShader("assest/shader/1入门/1.8.transform.vs", "assest/shader/1入门/1.8.transform.fs");// 顶点数据
    float vertices[] = {// positions          // texture coords0.5f,  0.5f, 0.0f,   1.0f, 1.0f, // top right0.5f, -0.5f, 0.0f,   1.0f, 0.0f, // bottom right-0.5f, -0.5f, 0.0f,   0.0f, 0.0f, // bottom left-0.5f,  0.5f, 0.0f,   0.0f, 1.0f  // top left 
    };
    unsigned int indices[] = {0, 1, 3, // first triangle1, 2, 3  // second triangle
    };
    // 顶点数组
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);// 加载纹理
    unsigned int texture1, texture2;
    // texture 1
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    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_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
    unsigned char* data = stbi_load(FileSystem::getPath("assest/textures/container.jpg").c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);
    // texture 2 和texture1一样
    .......
    // 告诉OpenGL两个采样器对应哪个纹理单元
    ourShader.use();
    ourShader.setInt("texture1", 0);
    ourShader.setInt("texture2", 1);// render loop
    while (!glfwWindowShouldClose(window))
    {// inputprocessInput(window);// renderglClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!// bind textures on corresponding texture unitsglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);// 此节重点在这///// 构造矩阵变换glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix firstglm::mat4 view = glm::mat4(1.0f);glm::mat4 projection = glm::mat4(1.0f);model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));// 注意,我们将矩阵向我们要进行移动场景的反方向移动。view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));// 透视投影矩阵projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);// 设置uniformourShader.use();unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model");unsigned int viewLoc = glGetUniformLocation(ourShader.ID, "view");// 3种不同的方式发送数据给ShaderglUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view[0][0]);ourShader.setMat4("projection", projection);// 渲染boxglBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    
    • 重点代码

      // 将物体绕着x轴旋转-55.0度
      model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
      // 注意,我们将矩阵向我们要进行移动场景的反方向移动。
      view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
      // 透视投影矩阵
      projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
      
  • 效果

    • 经过model矩阵实现的旋转+透视投影可看到的效果
      • 稍微向后倾斜至地板方向。
      • 离我们有一些距离。
      • 有透视效果(顶点越远,变得越小)。

例子2:更加3D

  • 代码改变

    与上一个例子相比的改变

    • 改变了顶点数据,顶点数据是一个箱子的36个顶点
    • 去除了索引缓冲与索引绘制
    • model矩阵不再是绕着x旋转-55度,而是绕着y轴旋转度数time(运行时间作为度数)
  • 代码

    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
    };
    model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
    
  • 效果

    请添加图片描述

    效果奇怪,奇怪的地方在于没有进行深度测试,导致后渲染的片段覆盖前渲染的片段,从而箱子的背面覆盖前面。

  • 如何修复

    • 由于OpenGL默认不进行深度测试,需要设置开启深度测试,开启后opengl自动完成

      只需在渲染代码前中加一句

      glEnable(GL_DEPTH_TEST);
      
    • 深度测试工作原理

      • OpenGL存储它的所有深度信息于一个Z缓冲,又称深度缓冲
      • GLFW会自动为你生成这样一个缓冲(就像它也有一个颜色缓冲来存储输出图像的颜色)
      • 深度值存储在每个片段里面(作为片段的z值),当片段想要输出它的颜色时,OpenGL会将它的深度值和z缓冲进行比较,如果当前的片段在其它片段之后,它将会被丢弃否则将会覆盖
  • 修复效果

例子3:箱子派对

  • 实现思路

    • 定义10个箱子的出生点

    • 循环10次

      每次model为单位矩阵,再将model矩阵进行平移到出生点,再可以加上旋转效果(代码顺序)

  • 代码

    float vertices[] = {-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,......
    };
    // 出生点-初始位置
    glm::vec3 cubePositions[] = {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)
    };
    // render box
    glBindVertexArray(VAO);
    for (unsigned int i = 0; i < 10; i++)
    {glm::mat4 model = glm::mat4(1.0f);model = glm::translate(model, cubePositions[i]);    // 先平移float angle = 20.0f * i * (float)glfwGetTime();model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));// 再旋转ourShader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    

    注意model矩阵,写代码的顺序是先平移再旋转,但是解读的话是先旋转再平移(请看本专栏中变换-矩阵的组合)。

  • 效果

相关文章:

LearnOpenGL-入门-8.坐标系统

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject LearnOpenGL中文官网&#xff1a;https://learnopengl-cn.github.io/ 文章目录坐标系统概述局部空间世界空…...

windows10使用wsl2安装docker

配环境很麻烦&#xff0c;想利用docker的镜像环境跑一下代码整个安装过程的原理是&#xff1a;windows使用docker&#xff0c;必须先安装一个linux虚拟机&#xff0c;才可运行docker&#xff0c;而采用wsl2安装虚拟机是目前最好的方法第一步 windows安装wsl2控制面板->程序-…...

Javascript的API基本内容(六)

一、正则表达式 1.定义规则 const reg /表达式/ 其中/ /是正则表达式字面量正则表达式也是对象 2.使用正则 test()方法 用来查看正则表达式与指定的字符串是否匹配如果正则表达式与指定的字符串匹配 &#xff0c;返回true&#xff0c;否则false 3.元字符 比如&#xff0…...

电压放大器和电流放大器的区别是什么意思

在日常电子实验测试中&#xff0c;很多电子工程师都会使用到电压放大器和电流放大器&#xff0c;但是很多新手工程师却无法区分两者的区别&#xff0c;下面就让安泰电子来为我们讲解电压放大器和电流放大器的区别是什么意思。 一、电压放大器介绍&#xff1a; 电压放大器是一种…...

cast提前!最简单有效的神经网络优化方法,没有之一!

做优化有时候真的很头疼&#xff0c;绞尽脑汁的想怎么做算法等价&#xff0c;怎么把神经网络各层指令流水起来&#xff0c;在确保整网精度的同时&#xff0c;又有高性能。 但有时做了半天&#xff0c;却发现流水根本就流不起来&#xff0c;总是莫名其妙地被卡住。 真的是一顿…...

LeetCode刷题——动态规划(C/C++)

文章目录[简单]买股票的最佳时机[简单]爬楼梯[中等]最长递增子序列[中等]最大连续子数组和[简单]买股票的最佳时机 原题链接 题解 min&#xff1a;今天之前买股的最低价 res&#xff1a;最大利润 每一天比较今天和往前的最低价差值能否比最大利润还大 class Solution { publ…...

车载智能终端TBOX

YD886 终端设备是基于GSM/WCDMA全网通讯方式的GPS定位移动终端,车载设备具有强大的车辆监控管理、CAN总线数据采集等功能&#xff0c;可以满足不同用户的需求&#xff0c;同时具备汽车行驶记录功能扩展应用。具体功能请以终端实际情况为准&#xff01; 一、移动管家 车载智能终…...

技术分担产品之忧(上):挑选有业务专家潜力的人

你好&#xff0c;我是王植萌&#xff0c;去哪儿网的高级技术总监、TC主席。从2014年起&#xff0c;担任一个部门的技术负责人&#xff0c;有8年技术总监经验、5年TC主席的经验。这节课我会从去哪儿网产研融合的经验出发&#xff0c;和你聊一聊怎么让技术分担产品之忧。 技术分…...

UVa 12569 Planning mobile robot on Tree (EASY Version) 树上机器人规划(简单版) BFS 二进制

题目链接&#xff1a;Planning mobile robot on Tree (EASY Version) 题目描述&#xff1a; 给定一棵树&#xff0c;树上有一个位置存在一个机器人&#xff0c;其他mmm个位置存在石头&#xff0c;保证初始状态一个结点最多一个物体&#xff08;一个石头或者一个机器人或者为空…...

intel的集成显卡(intel(r) uhd graphics) 配置stable diffusion

由于很多商务本没有独立显卡&#xff0c;只有Intel的集成显卡&#xff0c;在配置安装stable diffusion 时候需要特殊对待&#xff0c;参考不少帖子&#xff0c;各取部分现稍加整合。整体思路分两个部分&#xff1a;第一步是先配置环境&#xff0c;主要是安装Anaconda Pytorch&…...

【数据库的基础知识(2)】

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…...

Docker部署实战

文章目录Docker部署应用准备制作容器镜像启动容器上传镜像docker exec数据卷&#xff08;Volume&#xff09;声明原理实践Docker部署 应用准备 这一次&#xff0c;我们来用 Docker 部署一个用 Python 编写的 Web 应用。这个应用的代码部分&#xff08;app.py&#xff09;非常…...

RestTemplate 相关使用

RestTemplate介绍简单接口调用&#xff08;getForObject&#xff09;添加 Header 和 Cookie&#xff08;exchange&#xff09;介绍 在项目中&#xff0c;当我们需要远程调用一个 HTTP 接口时&#xff0c;我们经常会用到 RestTemplate 这个类。这个类是 Spring 框架提供的一个工…...

新手小白亚马逊注册最全教程在此

自从龙哥出了Walmart注册教程后&#xff0c;立刻看到私信有兄弟问这个亚马逊的注册。亚马逊是跨境电商的鼻祖&#xff0c;资源和流量是无容置疑的。作为一个重产品&#xff0c;轻店铺的平台&#xff0c;是比较看中客户体验的&#xff0c;要求卖家要有好的资源。而且亚马逊有强大…...

二分查找重复情况 找最左边或最右边的位置下标

目录二分找最左边二分找最右边综合应用(剑指offer)二分找最左边 核心思想: 先mid (lr)/2每次向左取整; 然后命中target的时候&#xff0c;右边界逼近到mid; 因为每次mid向左取整&#xff0c;mid命中target时l代替mid位置&#xff0c;则循环迭代最后会卡出重复数字最左侧的位置…...

智慧扫码点餐系统源码

智慧餐厅扫码点餐小程序系统源码 1. 开发语言&#xff1a;JAVA 2. 数据库&#xff1a;MySQL 3. 原生小程序 4. Saas 模式 5. 带调试部署视频 6、总后台管理端商家端门店端小程序用户端 智慧扫码点餐系统支持多店铺运营&#xff0c;单店铺运营以及连锁店铺运营。系统功能支…...

分布式环境并发场景下,如何操作抢红包(或者减少库存)

文章目录简介思考lua 对 redis 的原子操作其他解决方式一些问题简介 在分布式场景高并发环境中&#xff0c;无论是抢红包还是减库存&#xff0c;其实本质上都是如何处理高并发中共享资源的问题&#xff0c;保证高并发资源分配的安全性 相互学习&#xff0c;如有错误还请指正&…...

明星的孩子也在做的感统训练,真的有用吗?

林志颖曾经在社交网站晒过带他儿子“模拟过山车”的视频。孩子大脑前庭受到适当的刺激&#xff0c;可以有效地锻炼前庭平衡感。 除此之外&#xff0c;还能看见地上的感统教具&#xff1a;过河石、平衡桥&#xff0c;看来明星老爸在陪孩子做感统游戏的日常一点也不含糊。 其实在…...

守护进程与TCP通讯

目录 一.守护进程 1.1进程组与会画 1.2守护进程 二.创建守护进程 setsid函数&#xff1a; 三. TCP通讯流程 3.1三次握手&#xff1a; 3.2 数据传输的过程 3.3四次挥手 一.守护进程 1.1进程组与会画 进程组&#xff1a;进程组由一个进程或者多个进程组成&#xff0c;每…...

在线文本翻译能力新增14个直译模型,打造以中文为轴心语言的翻译系统

经济全球化的今天&#xff0c;人们在工作和生活中经常会与外语打交道。相较传播性较广的英语而言&#xff0c;其他语种的识别和阅读对大多数人来说是一件难事&#xff0c;此时就需要借助语言翻译软件来帮助理解。 华为 HMS Core 机器学习服务&#xff08;ML Kit&#xff09;翻…...

CVE-2022-42889 Apache Commons Text 漏洞

0x00 前言 所幸遇到&#xff0c;就简单看看&#xff0c;其中没有啥比较难的地方&#xff0c;仅做记录。10月13日的漏洞。 cve链接可以看下面这个&#xff1a; https://cve.mitre.org/cgi-bin/cvename.cgi?nameCVE-2022-42889 git地址&#xff1a; https://github.com/apache…...

20- widedeep及函数式构建模型 (TensorFlow系列) (深度学习)

知识要点 wide&deep: 模型构建中, 卷积后数据和原始数据结合进行输出.fetch_california_housing&#xff1a;加利福尼亚的房价数据&#xff0c;总计20640个样本&#xff0c;每个样本8个属性表示&#xff0c;以及房价作为target&#xff0c;所有属性值均为number&#xff0…...

大家一起做测试的,凭什么你现在拿20k,我却还只有10k?...

最近我发现一个神奇的事情&#xff0c;我一个97年的朋友居然已经当上了测试项目组长&#xff0c;据我所知他去年还是在深圳的一家创业公司做苦逼的测试狗&#xff0c;短短8个月&#xff0c;到底发生了什么&#xff1f; 于是我立刻私聊他八卦一番。 原来他所在的公司最近正在裁…...

>>数据管理:DAMA简介「考试和续期」

关于DAMA,这里就不再多做描述,可以参考以前写的一些简介或官方介绍。下面就考试再做一些详细介绍。 1 区别 CDGA:数据治理工程师(Certified Data Governance Associate),“DAMA中国”组织的数据治理方面的职业认证考试。 CDGP:数据治理专家(Certified Data Governa…...

React的生命周期详细讲解

什么是生命周期&#xff1f; 所谓的React生命周期&#xff0c;就是指组件从被创建出来&#xff0c;到被使用&#xff0c;最后被销毁的这么一个过程。而在这个过程中&#xff0c;React提供了我们会自动执行的不同的钩子函数&#xff0c;我们称之为生命周期函数。**组件的生命周期…...

蓝蓝算法二期工程day3,一万年太久,只争朝夕

思路&#xff1a; 最好想的是用hashmap&#xff0c;当然用c的话也可以用两个数组&#xff0c;一个数组用于存放字符串&#xff0c;自动对应ACSII码&#xff0c;一个将对应ACSII码的数字对应其下标&#xff0c;当然这也是用的映射的思想。 import java.util.*;public class Cac…...

程序代码的自动化生成方案设计

程序设计就能够适用这种代码自动化生成方法的前提是:PLC 程序代码具有高度重复性,执行的是相同数据处理或者逻辑判断,而相关变量组 是离 散 的,没 有规 律 可循 。以 I/O 变量和中间 变量的地 址 映 射 程序为例 ,程序代码为赋 值 语 句 ,高度重复;IO 变量和与 其 对应 的中间 …...

Go 稀疏数组学习与实现

仍然还是一个数组 基本介绍 一般就是指二维以上的数组 当一个数组中大部分元素是0 ,或者为同一个值的数组时,可以使用系数数组来保存该数组. 稀疏数组的处理方法: 记录数组一共有几行几列,有多少个不同的值把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程…...

MySQL 学习笔记(借鉴黑马程序员MySQL)

MySQL视频课链接 MySQL概述 数据库相关概念 数据库是存储数据的仓库&#xff0c;数据是有组织的进行存储&#xff08;DataBase&#xff09; 数据库管理系统是操纵和管理数据库的大型软件&#xff08;DataBase Management System&#xff09; SQL是操作关系型数据库的编程语…...

中级工程师职称申报到底需要参加答辩不?

获得中级工程师职称的方式有认定、评审、考试这几种形式。 甘建二老师先来简单说一下关于认定和考试这两种&#xff1a; 1.认定&#xff1a;中级职称认定一般是根据各地职称认定政策&#xff0c;如果你想走认定渠道&#xff0c;首先本人简历条件、业绩、奖项等非常优秀&#…...

MM32开发教程(LED灯)

文章目录前言一、MM32介绍和STM32的区别二、板载LED灯原理图三、代码编写总结前言 今天将为大家介绍一款性能高体积小的MM32&#xff0c;这款开发板出自百问网团队。他就是灵动的MM32F3273&#xff0c;他体积非常小便于携带。 有128KB的SRAM、512KB的Flash、而且还支持双TypeC…...

win10安装docker

1.win10安装docker&#xff0c;前提必须是要安装WSL2。 现在Docker Desktop默认使用WSL 2来运行&#xff0c;而不是以前的Hyper-V。 WSL2 全称是Windows Subsystem on Linux。意思是&#xff0c;在win10&#xff0c;可以直接启动一个Linux。因为docker依赖Linux内核。 可查看…...

设计模式系列 - 代理模式及动态代理详解

定义 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下&#xff0c;一个对象不适合或者不能直接引用另一个对象&#xff0c;而代理对象可以在客户端和目标对象之间起到中介的作用。 结构 抽象角色&#xff1a;通过接口或抽象类声明真实角色实现的业务方法。 代…...

【分享】订阅集简云畅捷通T+cloud连接器自动同步财务费用单至畅捷通

方案场景 伴随公司发展和数字化水平提高&#xff0c;大量的财务单据需要手动审核和录入&#xff0c;这些重复机械的操作占据大量人力&#xff0c;同时极容易出现数据出错或丢失等情况&#xff0c;严重影响着企业经营效率。 使用集简云提供服务的畅捷通TCloud钉钉连接器完成财…...

GPT的发展历程

GPT是当前最火的人工智能技术之一&#xff0c;自推出以来就广受关注。但大家对这个技术了解多少&#xff0c;又知道它经历了什么&#xff1f; GPT的诞生离不开谷歌在人工智能领域的努力和研究。2004年&#xff0c;谷歌成立了人工智能实验室&#xff08;现已成为谷歌 AI实验室&…...

iOS开发笔记之九十八——关于Memory Leak总结笔记

*****阅读完此文&#xff0c;大概需要3分钟******关于Memory leak&#xff08;内存泄漏&#xff09;的问题&#xff0c;如果是面试被问这个问题以及此类问题&#xff0c;主要涉及下面3个方面&#xff1a;内存泄漏的常见场景有哪些&#xff0c;列举几个常见的例子&#xff1f;开…...

HTML基础语法

一 前端简介构成语言说明结构HTML页面元素和内容表现CSS网页元素的外观和位置等页面样式&#xff08;美化&#xff09;行为JavaScript网页模型的定义和页面交互二 HTML1.简介HTML&#xff08;Hyper Text Markup Language&#xff09;&#xff1a;超文本标记语言。网页结构整体&…...

微软新版必应gpt人工智能体验教程

大家好,我是雄雄,欢迎关注微信公众号:** 雄雄的小课堂 ** 现在是:2023年2月28日18:35:02 前言 前几天,发了一篇文章,主要介绍了如何申请新必应的内测名单,其实一共也就那几步,然后等着就行: 文章连接:new bing如何快速申请内测资格,从而体验人工智能? 今天,终于…...

你问我答|虚拟机、容器和无服务器,怎么选?

在新技术层出不穷的当下,每家企业都希望不断降低成本,并提高运营效率,一个方法就是寻找不同的技术方案来优化运营。      例如,曾经一台服务器只能运行一个应用(裸机);接着,一台服务器的资源可以划分为多个块,从而运行多个应用(虚拟化);再到后来,应用越来越多,为了方便它们…...

某建筑设计研究院“综合布线管理软件”应用实践

某建筑设计研究院有限公司&#xff08;简称“某院”&#xff09;隶属于国务院国资委直属的大型骨干科技型中央企业。“某院”前身为中央直属设计公司&#xff0c;创建于1952年。成立近70年来&#xff0c;始终秉承优良传统&#xff0c;致力于推进国内勘察设计产业的创新发展&…...

R语言绘制SCI论文中常见的箱线散点图,并自动进行方差分析计算显著性水平

显著性标记箱线散点图 本篇笔记的内容是在R语言中利用ggplot2&#xff0c;ggsignif&#xff0c;ggsci&#xff0c;ggpubr等包制作箱线散点图&#xff0c;并计算指定变量之间的显著性水平&#xff0c;对不同分组进行特异性标记&#xff0c;最终效果如下。 加载R包 library(ggplo…...

redux-saga

redux-saga 官网&#xff1a;About | Redux-Saga 中文网&#xff1a;自述 Redux-Saga redux-saga 是一个用于管理 异步获取数据(副作用) 的redux中间件&#xff1b;它的目标是让副作用管理更容易&#xff0c;执行更高效&#xff0c;测试更简单&#xff0c;处理故障时更容易… …...

【C++】-- 智能指针

目录 智能指针意义 智能指针的使用及原理 RAII 智能指针的原理 std::auto_ptr std::auto_ptr的模拟实现 std::unique_ptr std::unique_ptr模拟实现 std::shared_ptr std::shared_ptr的模拟实现 循环引用问题 智能指针意义 #问&#xff1a;为什么需要智能指针&#…...

数据结构与算法——4时间复杂度分析2(常见的大O阶)

这篇文章是时间复杂度分析的第二篇。在前一篇文章中&#xff0c;我们从0推导出了为什么要用时间复杂度&#xff0c;时间复杂度如何分析以及时间复杂度的表示三部分内容。这篇文章&#xff0c;是对一些常用的时间复杂度进行一个总结&#xff0c;相当于是一个小结论 1.常见的大O…...

IIS解析漏洞

IIS 6.0在解析文件时存在以下两个解析漏洞。 ①当建立*.asa、*.asp格式的文件夹时&#xff0c;其目录下的任意文件都将被IIS当作asp文件来解析。 例如&#xff1a;建立文件夹 parsing.asp&#xff0c;在 parsing.asp 文件夹内新建一个文本文档 test.txt&#xff0c;其内容为&…...

2023 年腾讯云轻量和CVM服务器租用价格表出炉(CPU/内存/带宽/系统盘)

腾讯云服务器的价格表是用户比较关心的问题&#xff0c;服务器的价格组成包括云服务器的机型价格、磁盘价格和宽带价格&#xff0c;主机教程网来详细说下腾讯云最新的云服务器价格表。我们以北京一区、Linux系统的云服务器为例&#xff0c;其他地域的价格会有所差异&#xff0c…...

Java学习之路002——面向对象编程

【说明】部分内容来源于网络&#xff0c;如有冲突&#xff0c;请联系作者删除。 一、面向对象编程(OOP) 2.1 对象和类的关系 2.2 面向对象的特征 2.2.1 封装 2.2.2 继承 2.2.3 多态 3、抽象 使用abstract关键字修饰的类或者方法 定义抽象类(使用abstract) // 1、定义抽象方法…...

VR直播丨颠覆性技术革命,新型直播已经到来

细数当下最火热的营销手段&#xff0c;首先浮现脑海的无疑是“直播”。前有罗永浩、李佳琦&#xff0c;后有刘畊宏和东方甄选&#xff0c;直播如日中天&#xff0c;俨然成了大众足不出户就能休闲娱乐的重要途径。 而随着虚拟现实在“十四五规划”中被列入“建设数字中国”数字…...

【微信小程序】-- WXSS 模板样式- rpx import (十三)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…...

Biotin-PEG-SVA,生物素聚乙二醇琥珀酰亚胺戊酸酯,可用于检测或分子标记

Biotin-PEG-SVA 结构式&#xff1a;PEG分子量&#xff1a; 1000&#xff0c;2000&#xff0c;3400&#xff0c;5000&#xff0c;10000中文名称&#xff1a;生物素聚乙二醇琥珀酰亚胺戊酸酯&#xff0c;生物素-PEG-琥珀酰亚胺戊酸酯英文名称&#xff1a;Biotin-PEG-SVA &#xf…...