WebGL 视图矩阵、模型视图矩阵
目录
立方体由三角形构成
视点和视线
视点、观察目标点和上方向
视点:
观察目标点:
上方向:
在WebGL中,观察者的默认状态应该是这样的:
视图矩阵程序(LookAtTriangles.js)
实际上,“根据自定义的观察者状态,绘制观察者看到的景象”与“使用默认的观察状态,但是对三维对象进行平移、旋转等变换,再绘制观察者看到的景象”,这两种行为是等价的。(归根结底:不论视图怎样变化,无疑就是旋转、平移等操作,最终本质上都是对物体进行相反方向的旋转平移(默认的视角))
移动视点和移动被观察对象等效
从指定视点观察旋转后的三角形
<旋转后顶点坐标>=<旋转矩阵>×<原始顶点坐标>
<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转后顶点坐标>
<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转矩阵>×<原始顶点坐标>
<视图矩阵>×<模型矩阵>×<原始顶点坐标>
模型视图矩阵程序(LookAtRotatedTriangles.js)
模型视图矩阵
<模型视图矩阵>=<视图矩阵>×<模型矩阵>
<模型视图矩阵>×<顶点坐标>
立方体由三角形构成
三维物体也是由二维图形(特别是三角形)组成的。如下图所示,12个三角形组成了一个立方体。
既然三维物体是由三角形组成的,那么则需要逐个绘制组成物体的每个三角形,最终就可以绘制出整个三维物体了。但是,三维与二维还有一个显著区别:在绘制二维图形时,只需要考虑顶点的x和y坐标,而绘制三维物体时,还得考虑它们的深度信息(depth information)。那就开始吧,首先我们来研究一下如何定义三维世界的观察者:在什么地方、朝哪里看、视野有多宽、能看多远。
视点和视线
三维物体与二维图形的最显著区别就是,三维物体具有深度,也就是Z轴。因此,你会遇到一些之前不曾考虑过的问题。事实上,我们最后还是得把三维场景绘制到二维的屏幕上,即绘制观察者看到的世界,而观察者可以处在任意位置观察。为了定义一个观察者,你需要考虑以下两点:
● 观察方向,即观察者自己在什么位置,在看场景的哪一部分?
● 可视距离,即观察者能够看多远?
我们将观察者所处的位置称为视点(eye point),从视点出发沿着观察方向的射线称作视线(viewing direction)。本次将研究如何通过视点和视线来描述观察者。到下面我们再来研究“观察者能看多远”的问题。
我们来创建一个新的示例程序LookAtTriangles。在程序中,视点位于(0.20,0.25,0.25),视线向着原点(0,0,0)方向,可以看到原点附近有三个三角形。程序中的这三个三角形前后错落摆放,以帮助你理解三维场景中深度的概念。下图显示了LookAtTriangles的运行结果。
视点、观察目标点和上方向
为了确定观察者的状态,你需要获取两项信息:视点,即观察者的位置;观察目标点(look-at point),即被观察目标所在的点,它可以用来确定视线。此外,因为我们最后要把观察到的景象绘制到屏幕上,还需要知道上方向(up direction)。有了这三项信息,就可以确定观察者的状态了。下面将逐一进行解释(见下图)。
视点:
观察者所在的三维空间中位置,视线的起点。在接下来的几节中,视点坐标都用(eyeX,eyeY,eyeZ)表示。
观察目标点:
被观察目标所在的点。视线从视点出发,穿过观察目标点并继续延伸。注意,观察目标点是一个点,而不是视线方向,只有同时知道观察目标点和视点,才能算出视线方向。观察目标点的坐标用(atX,atY,atZ)表示。
上方向:
最终绘制在屏幕上的影像中的向上的方向。试想,如果仅仅确定了视点和观察点,观察者还是可能以视线为轴旋转的(如下图所示,头部偏移会导致观察到的场景也偏移了)。所以,为了将观察者固定住,我们还需要指定上方向。上方向是具有3个分量的矢量,用(upX,upY,upZ)表示。
在WebGL中,我们可以用上述三个矢量创建一个视图矩阵(view matrix),然后将该矩阵传给顶点着色器。视图矩阵可以表示观察者的状态,含有观察者的视点、观察目标点、上方向等信息。之所以被称为视图矩阵,是因为它最终影响了显示在屏幕上的视图,也就是观察者观察到的场景。根据提供的Matrix4.setLookAt()函数可以根据上述三个矢量:视点、观察点和上方向,来创建出视图矩阵 (矩阵库 WebGL矩阵变换库_山楂树の的博客-CSDN博客)。
在WebGL中,观察者的默认状态应该是这样的:
● 视点位于坐标系统原点(0,0,0)。
● 视线为Z轴负方向,观察点为(0,0,-1)
如果将上方向改为X轴正半轴方向(1,0,0),你将看到场景旋转了90度。
创建这样一个矩阵,你只需要简单地使用如下代码(见下图)。
现在,你已经了解了setLookAt()函数,下面来看示例程序的代码。
视图矩阵程序(LookAtTriangles.js)
程序显示了LookAtTriangles.js的代码,我们修改了视点,然后绘制了3个三角形,如上图三角形所示。实际上这3个三角形的颜色分别为蓝色到红色、黄色到红色和绿色到红色的渐变色。
var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_ViewMatrix * a_Position;\n' +' v_Color = a_Color;\n' +'}\n';var FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_FragColor = v_Color;\n' +'}\n';function main() {var canvas = document.getElementById('webgl');var gl = getWebGLContext(canvas);if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// 设置顶点坐标和颜色(蓝色三角形在最前面)var n = initVertexBuffers(gl);gl.clearColor(0, 0, 0, 1);// 获取u_ViewMatrix变量的存储地址var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');// 设置视点、视线和上方向var viewMatrix = new Matrix4();viewMatrix.setLookAt(0.20, 0.25, 0.25, 0, 0, 0, 0, 1, 0);// 将视图矩阵传给u_ViewMatrix变量gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);gl.clear(gl.COLOR_BUFFER_BIT);// 绘制三角形gl.drawArrays(gl.TRIANGLES, 0, n);
}function initVertexBuffers(gl) {var verticesColors = new Float32Array([// 顶点和坐标颜色0.0, 0.5, -0.4, 0.4, 1.0, 0.4, // 绿色三角形在最后面-0.5, -0.5, -0.4, 0.4, 1.0, 0.4,0.5, -0.5, -0.4, 1.0, 0.4, 0.4, 0.5, 0.4, -0.2, 1.0, 0.4, 0.4, // 黄色三角形在中间-0.5, 0.4, -0.2, 1.0, 1.0, 0.4,0.0, -0.6, -0.2, 1.0, 1.0, 0.4, 0.0, 0.5, 0.0, 0.4, 0.4, 1.0, // 蓝色三角形在最前面-0.5, -0.5, 0.0, 0.4, 0.4, 1.0,0.5, -0.5, 0.0, 1.0, 0.4, 0.4, ]);var n = 9;// 创建缓冲区对象var vertexColorbuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;var a_Position = gl.getAttribLocation(gl.program, 'a_Position');gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);var a_Color = gl.getAttribLocation(gl.program, 'a_Color');gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);gl.bindBuffer(gl.ARRAY_BUFFER, null);return n;
}
首先,来看一下initVertexBuffers()函数(第42行)。verticesColors数组包含了3个三角形共计9个顶点的数据,而且顶点坐标的z分量也不再是0了。接着我们创建了缓冲区对象(第57行),并将数组中的数据填了进去(第58~59行)。此外,我们还把gl.drawArrays()的第3个参数改成了9(第39行),因为这里共有9个顶点。
然后,需要建立视图矩阵(包含了视点、视线和上方向信息)并传给顶点着色器。为此,我们先创建了一个Matrix4对象viewMatrix(第33行),然后用setLookAt()方法将其设置为视图矩阵(第34行),最后将视图矩阵中的元素传给顶点着色器中的u_ViewMatrix变量(第36行)。
实际上,“根据自定义的观察者状态,绘制观察者看到的景象”与“使用默认的观察状态,但是对三维对象进行平移、旋转等变换,再绘制观察者看到的景象”,这两种行为是等价的。(归根结底:不论视图怎样变化,无疑就是旋转、平移等操作,最终本质上都是对物体进行相反方向的旋转平移(默认的视角))
举个例子,默认情况下视点在原点,视线沿着Z轴负方向进行观察。假如我们将视点移动到(0,0,1),如下图(左)所示。这时,视点与被观察的三角形在Z轴上的距离增加了1.0个单位。实际上,如果我们使三角形沿Z轴负方向移动1.0个单位,也可以达到同样的效果,因为观察者看上去是一样的,如下图(右)所示。
移动视点和移动被观察对象等效
事实上,上述过程就发生在示例程序LookAtTriangles.js中。根据视点、观察点和上方向参数,setLookAt()方法计算出的视图矩阵恰恰就是“沿着Z轴负方向移动1.0个单位”的变换矩阵。所以,把这个矩阵与顶点坐标相乘,就相当于获得了“将视点设置在(0.0,0.0,1.0)”的效果。视点移动的方向与被观察对象(也就是整个世界)移动的方向正好相反。对于视点的旋转,也可以采用类似的方式。
“改变观察者的状态”与“对整个世界进行平移和旋转变换”,本质上是一样的,它们都可以用矩阵来描述。接下来,我们将从一个指定的视点来观察旋转后的三角形。
从指定视点观察旋转后的三角形
现在将修改LookAtTriangles程序来绘制一个从指定位置看过去的旋转后的三角形。这时,我们需要两个矩阵:旋转矩阵(表示三角形的旋转)和视图矩阵(表示观察世界的方式)。首先有一个问题是,以怎样的顺序相乘这两个矩阵。
我们知道,矩阵乘以顶点坐标,得到的结果是顶点经过矩阵变换之后的新坐标。也就是说,用旋转矩阵乘以顶点坐标,就可以得到旋转后的顶点坐标。
用视图矩阵乘以顶点坐标会把顶点变换到合适的位置,使得观察者(以默认状态)观察新位置的顶点,就好像在观察者处在(视图矩阵描述的)视点上观察原始顶点一样。现在要在某个视点处观察旋转后的三角形,我们需要先旋转三角形,然后从这个视点来观察它。换句话说,我们需要先对三角形进行旋转变换,再对旋转后的三角形进行与“移动视点”等效的变换。我们按照上述顺序相乘两个矩阵。具体看一下等式。
我们知道,如果想旋转图形,就需要用旋转矩阵乘以旋转前的顶点坐标:
<旋转后顶点坐标>=<旋转矩阵>×<原始顶点坐标>
用视图矩阵乘以旋转后的顶点坐标,就可以获得“从视点看上去”的旋转后的顶点坐标:
<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转后顶点坐标>
将第1个式子代入第2个,可得:
<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转矩阵>×<原始顶点坐标>
除了旋转矩阵,你还可以使用平移、缩放等基本变换矩阵或它们的组合,这时矩阵被称为模型矩阵(model matrix)。这样,上式就可以写成:
<视图矩阵>×<模型矩阵>×<原始顶点坐标>
示例程序在着色器中实现了该式。很简单,直接照着该式修改顶点着色器。修改后的LootAtRotatedTriangles程序实现了上述变换,如下图所示。图中白色虚线为旋转前三角形的所在位置,可以看到三角形确实被旋转过了。
模型视图矩阵程序(LookAtRotatedTriangles.js)
LookAtRotatedTriangles.js与LookAtTriangles.js相比,只有几处小改动:加入了uniform变量u_ModelMatrix;JavaScript中的main()函数将模型矩阵传给该变量。相应的代码如下所示。
首先,顶点着色器中添加了uniform变量u_ModelMatrix(第7行),该变量从JavaScript中接收模型矩阵,以实现等式<视图矩阵>×<模型矩阵>×<原始顶点坐标>。
JavaScript的main()函数已经有了与视图矩阵相关的代码,只需添加几行计算和传入旋转矩阵的代码,将三角形绕Z轴旋转10度。第53行代码实现了获取u_ModelMatrix变量的存储地址,第64行实现了创建一个新的矩阵对象modelMatrix,调用Matrix.setRotate()将其设为旋转矩阵(第65行),然后传给顶点着色器中的u_ModelMatrix(第69行)。
运行示例程序,顶点坐标依次与旋转矩阵和视图矩阵相乘,最终获得了预期的效果。如上图所示,即先用u_ModelMatrix旋转三角形,再将旋转后的坐标用u_ViewMatrix变换到正确的位置,使其看上去就像是从指定视点处观察一样。
模型视图矩阵
在LookAtRotatedTriangle.js中,着色器实现了式(视图矩阵×模型矩阵×原始坐标)。这样,程序对每个顶点都要计算视图矩阵×模型矩阵。如果顶点数量很多,这一步操作就会造成不必要的开销。这是因为,无论对哪个顶点而言,式(视图矩阵×模型矩阵×原始坐标)中的两个矩阵相乘的结果都是一样的。所以我们可以在JavaScript中事先把这两个矩阵相乘的结果计算出来,再传给顶点着色器。这两个矩阵相乘得到的结果被称为模型视图矩阵(model view matrix),如下所示:
<模型视图矩阵>=<视图矩阵>×<模型矩阵>
式视图矩阵×模型矩阵×原始坐标可以重写为下式
<模型视图矩阵>×<顶点坐标>
新的示例程序LookAtRotatedTriangles_mvMatrix.js按照式<模型视图矩阵>×<顶点坐标>重写了LookAtRotatedTriangles中的代码,如下所示。
顶点着色器中出现了新的uniform变量u_mvMatrix,它参与了对gl_Position的计算(第9行)。顶点着色器执行的流程与最初的LookAtTriangles.js中一样(除了uniform变量的名称)。
在JavaScript代码中,我们分别计算出了视图矩阵viewMatrix和模型矩阵modelMatrix(第59~63行),就像在LookAtTriangle.js中一样。然后,我们调用Matrix4.multiply()方法使这两个矩阵相乘,并将结果赋值给modelviewMatrix(第66行)。注意,我们是在viewMatrix上调用了multiply()方法,并传入modelMatrix为参数,所以这样做的结果实际上就是modelViewMatrix=viewMatrix*modelMatrix。因为在JavaScript中,我们不能像在GLSL ES中那样直接使用*号来进行矩阵相乘,而需要用矩阵库所提供的方法。
得到了modelViewMatrix后,就将它传给着色器的u_ModelMatrix变量(第69行)。运行程序,效果如下图所示。
最后还需要指出,示例程序显式地把视图矩阵和模型矩阵单独计算出来,再相乘为模型视图矩阵(第59~66行),是为了更好地表达模型视图矩阵的由来。实际上,只需要一行代码就可以计算出模型视图矩阵了:(计算出视图矩阵,再将视图矩阵与模型矩阵(当前只有旋转)相乘)
相关文章:
WebGL 视图矩阵、模型视图矩阵
目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点: 观察目标点: 上方向: 在WebGL中,观察者的默认状态应该是这样的: 视图矩阵程序(LookAtTriangles.js) 实际上&…...
Python 3 – 文件 readline() 方法
Python 3 – 文件 readline() 方法|极客笔记 # 打开文件 file open("example.txt", "r")# 读取文件中的一行数据 line file.readline() while line:# 移除行尾的换行符print(line.strip())# 读取文件中的下一行数据line file.readline()# 关闭文件 file…...
如何在微软Edge浏览器上一键观看高清视频?
编者按:视频是当下最流行的媒体形式之一。但由于视频压缩、网络不稳定等原因,我们常常可以看到互联网上的很多视频其画面质量并不理想,尤其是在浏览器端,这极大地影响了观看体验。不过,近期微软 Edge 浏览器推出了一项…...
Telegram BoT的主流项目盘点
目录 DeFi 类 数据分析类 空投埋伏交易 其他 Telegram Bot赛道的发展趋势预测 Telegram BoT赛道发展较快,具体来看可以分为DeFi 类、数据分析类、空投埋伏交易类以及其他。 DeFi 类 Unibot(交易)、Banana Gun、WagieBot(交…...
PTA 甲级 1044 Shopping in Mars
题目链接 思路:前缀和滑动窗口 #include<bits/stdc.h> #define MAXN 100010 using namespace std; int a[MAXN];int main(){int n,m;cin>>n>>m;//n数量 m金额for(int i1;i<n;i){int t;cin>>t;a[i]a[i-1]t;//前缀和}vector<pair<in…...
Linux学习之MyCat实现分库分表
环境准备 先准备一套MySQL主从服务器,可参考MySQL主从配置配置MyCat服务 资源下载 网盘链接: https://pan.baidu.com/s/1cLTMH_e1-6loc_gF9ZNHTg?pwda63n 提取码: a63n MyCat配置 # 1)安装mycat软件 //安装jdk [rootmycat58 upload]# yum -y insta…...
DirectX12(d3d12)初始化
一、前置要求 Windows 10及以上(安装有DirectX12)VisualStudio 2022 二、DirectX12入门 1.引用头文件 #include<Windows.h> #include<d3d12.h> #include<dxgi1_4.h>2.注册窗口类并初始化窗口 这里我们调用Windows API 通过应用程序的句柄来注册一个唯一…...
算法通关村-----回溯模板如何解决排列组合问题
组合总和 问题描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限…...
【1++的C++进阶】之智能指针
👍作者主页:进击的1 🤩 专栏链接:【1的C进阶】 文章目录 一,什么是智能指针二,为什么需要智能指针三,智能指针的发展 一,什么是智能指针 要了解智能指针,我们先要了解RA…...
一百七十九、Linux——Linux报错No package epel-release available
一、目的 在Linux中配置Xmanager服务时,执行脚本时Linux报错No package epel-release available 二、解决措施 (一)第一步,# wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm (二&…...
【AI视野·今日CV 计算机视觉论文速览 第248期】Mon, 18 Sep 2023
AI视野今日CS.CV 计算机视觉论文速览 Mon, 18 Sep 2023 Totally 83 papers 👉上期速览✈更多精彩请移步主页 Interesting: 📚Robust e-NeRF,处理高速且大噪声事件相机流的NERF模型。(from NUS新加坡国立) 稀疏噪声事件与稠密事件数据的区别:…...
解决Vue项目中的“Cannot find module ‘vue-template-compiler‘”错误
1. 问题描述 在Vue项目中,当我们使用Vue的单文件组件(.vue文件)时,有时会遇到以下错误信息: ERROR: Cannot find module vue-template-compiler这个错误通常发生在我们使用Vue的版本不匹配或者缺少必要的依赖模块时。…...
tensorflow基础
windows安装tensorflow anaconda或者pip安装tensorflow,tensorflow只支持win7 64系统,本人使用tensorflow1.5版本(pip install tensorflow1.5) tensorboard tensorboard只支持chrome浏览器,而且加载过程中可能有一段…...
spring_注解笔记
spring使用注解开发 文章目录 1.前提1 Bean2 属性注入3 衍生的注解4.自动装配5 作用域 1.前提 步骤1: 要使用注解开发,就必须要保证AOP包的导入 步骤2: xml文件添加context约束 步骤3: 配置注解的支持 <context:annotation-…...
c++运算符重载
目录 运算符重载的基本概念 重载加号运算符() 类内实现 类外实现 运算符重载碰上友元函数 可重载和不可重载的运算符 可重载的运算符 不可重载的运算符 重载自加自减运算符(a a) 智能指针 重载等号运算符() 重载等于和不等运算符(…...
vue子组件向父组件传参的方式
在Vue中,子组件向父组件传递参数可以通过自定义事件和props属性来实现。下面是一些关键代码示例: 1. 使用自定义事件: 在子组件中,通过 $emit 方法触发一个自定义事件,并传递参数。 <template><button cli…...
代码随想录Day41| 343. 整数拆分 |
343. 整数拆分 class Solution { public:int integerBreak(int n) {vector<int> f(n1,0);f[2]1;for(int i3;i<n;i){for(int j1;j<i-1;j){f[i]max(f[i],max(f[i-j]*j,(i-j)*j));}}return f[n];} }; 96. 不同的二叉搜索树 class Solution { public:int numTrees(int…...
工厂模式-(简单工厂模式)
首先看一下设计模式的六大原则 设计模式的六大原则 1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概…...
V8引擎是如何提升对象属性访问速度的?
JavaScript 中的对象是由一组组属性和值的集合,从 JavaScript 语言的角度来看,JavaScript 对象像一个字典,字符串作为键名,任意对象可以作为键值,可以通过键名读写键值。 然而在 V8 实现对象存储时,并没有…...
彩色相机工作原理——bayer格式理解
早期,图像传感器只能记录光的强弱,无法记录光的颜色,所以只能拍摄黑白照片。 1974年,拜尔提出了bayer阵列,发明了bayer格式图片。不同于高成本的三个图像传感器方案,拜尔提出只用一个图像传感器,在其前面放…...
IDEA中DEBUG技巧
Debug 介绍 Debug 设置 如上图标注 1 所示,表示设置 Debug 连接方式,默认是 Socket。Shared memory 是 Windows 特有的一个属性,一般在 Windows 系统下建议使用此设置,相对于 Socket 会快点。 ## Debug 常用快捷键 Win 快捷键M…...
人工智能训练师
人工智能训练师是一个较新的职业,2020年2月才被正式纳入国家职业分类目录。他们主要负责在人工智能产品使用过程中进行数据库管理、算法参数设置、人机交互设计、性能测试跟踪及其他辅助作业。 这个职业的背景源于AI公司从客户(用户)那里获取…...
【业务功能118】微服务-springcloud-springboot-Kubernetes集群-k8s集群-KubeSphere-OpenELB部署及应用
OpenELB部署及应用 一、OpenELB介绍 网址: openelb.io OpenELB 是一个开源的云原生负载均衡器实现,可以在基于裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。OpenELB 项目最初由 KubeSphere 社区发…...
Unity中Shader的模板测试
文章目录 前言什么是模板测试1、模板缓冲区2、模板缓冲区中存储的值3、模板测试是什么(看完以下流程就能知道模板测试是什么)模板测试就是在渲染,后渲染的物体前,与渲染前的模板缓冲区的值进行比较,选出符合条件的部分…...
Scala 高阶:Scala中的模式匹配
一、概述 Scala中的模式匹配(case)类似于Java中的switch...case,但是Scala的模式匹配功能更为强大。通过模式匹配,可以匹配更复杂的条件和数据结构,包括常量、类型、集合、元组等。而 Java 的 switch 语句只能用于匹配…...
分子生物学——分子机器
分子生物学——分子机器 文章目录 前言一、2016年度诺贝尔化学奖1.1. 介绍1.2. 什么是分子机器?1.3. 分子机器的意义 总结 前言 对于本次搜集分子生物学领域的一个诺贝尔奖的有关内容的作业 参考文献: https://www.cas.cn/zt/sszt/2016nobelprize/hxj/2…...
【简历优化】这套「实习、初级、中级」测试工程师求职简历模板,建议收藏。
历时2年,7000粉丝问答,帮助上百位“刚培训毕业”、“1~3年经验”的软件测试伙伴,成功入职! 我将这些问题内容,会持续更新记录在 「软件测试」求职指南 专栏。 求职简历中的误区 对于简历应该具备哪些模块,…...
vue中展示json数据的方法
推荐插件:bin-code-editor (gitee.io) bug-1:编辑器无法显示数据 原因:组件层级套用太深,导致无法显示数据 解决办法:减少在孙子及后代组件中使用插件。...
【SG滤波】三阶滤波、五阶滤波、七阶滤波(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
2013 ~【VUE+ ElementUI】——【上传、下载】进度计算
【VUE ElementUI】——【上传、下载】进度计算 上传:FormData方式上传,监听 onUploadProgress下载:blob文件流下载,监听 onDownloadProgress 上传:FormData方式上传,监听 onUploadProgress <el-upload:…...
蜂蜜网站建设/googleseo推广
win10控制台打不开提示管理员已阻止mmc.exe怎么办?最近有win10用户在打开控制台的时候发现打不开了,提示管理员已阻止mmc.exe。这是怎么回事呢?我们该如何解决控制台打不开提示管理员已阻止mmc.exe的问题呢?首先我们先了解一下mmc…...
福建漳州网站建设费用/什么是关键词搜索
1. where条件中有or,除非or的所有字段都有索引,只要有一个没有索引,就不走索引上面name和id都有索引上面money没有索引2.对于多列索引,第一列会使用索引,单独其他列不会,用or连接多列不会使用索引,用and会使…...
网页设计与网站建设奥鹏考试答案/站长收录平台
为什么80%的码农都做不了架构师?>>> 各位ccflow 爱好者: 最近推出一些ccflow5的视频教程,如下: http://video.sina.com.cn/v/b/102317000-1618288504.html 驰骋工作流引擎-同表单分合流设计过程 http://video.sina.com.cn/v/b/102314852-…...
如何在网站后台做超链接到文档/女教师遭网课入侵直播录屏曝光se
《三体》的第三体一个宇宙的时代(不以年计),书中的故事主角永存,其他所有被时间洗涮着。结局:所有文明生存的空间被自己玩完,有文明向宇宙中所有 100 多万个文明发出了信息。但一切已成定局。故事小结&…...
做任务领游戏的网站/百度股市行情上证指数
1.环境描述Centos 72.安装步骤通过命令yum install docker安装等待下载安装…,出现下图,按y继续继续等待…出现下图按y继续再继续等待…知道出现上图表示安装完毕3.测试安装是否成功执行命令docker后,如果与下图内容一致 则表示成功4.启动docker我们在执…...
石岩网站建设 0755/seo关键词优化培训班
首先要在windows下解压一个windows版本的hadoop 然后在配置他的环境变量,同时要把hadoop的share目录下的hadoop下的相关jar包拷贝到esclipe 然后Build Path 下面上代码 import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException…...