算法
奇偶链表
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
var oddEvenList = function(head) {
if(!head || !head.next){
return head;
}
var odd = head;
var even = head.next;
var tmp = even;
while(even && even.next){
odd.next = even.next;
odd = odd.next;
even.next = odd.next;
even = even.next;
}
odd.next = tmp
return head
};
可视空间
可视空间分两种:正射投影和透视投影
正射投影中平行的光 照射到与其平行的物体就变成点或者线了,看不到平行物体的侧面
透视投影中平行的光实际上发散出去的(就像人眼看平行的铁轨,明明是平行的,但是透视效果确实两个平行铁轨越远越相较于某一点),实际的光是不平行的 当然就可以看到物体的侧面。
正射投影
正射投影是的可视空间由近裁剪面和远裁剪面决定。接近视点的面试近裁剪面,投影位置为远裁剪面,我们实际看到的内容就仅仅是可视空间中的内容
当我们不断调整近裁剪面和远裁剪面时,如果图形不在可视空间内之后就会看不见
var VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_ProjMatrix;
varying vec4 v_Color;
void main() {
gl_Position = u_ProjMatrix * a_Position;
gl_PointSize = 10.0;
v_Color = a_Color;
}
`;
var FSHADER_SOURCE = `
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;
var gl = canvas.getContext('webgl');
initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)
this.gl = gl;
var n = this.initVertexBuffers(gl)
var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
//设置视点、视线、上方向
var projMatrix = new Matrix4();
document.onkeydown = function (ev) {
keydown(ev, gl, n, u_ProjMatrix,projMatrix);
};
draw(gl, n, u_ProjMatrix, projMatrix);
var g_near = 0.0, g_far = 0.5;
function keydown(ev, gl, n, u_ProjMatrix, projMatrix) {
switch (ev.keyCode){
case 39: g_near += 0.01; break; //right
case 37: g_near -= 0.01; break; //left
case 38: g_far += 0.01; break; //up
case 40: g_far -=0.01; break; //down
default: return;
}
draw(gl, n, u_ProjMatrix, projMatrix);
}
function draw(gl, n, u_ProjMatrix, projMatrix) {
projMatrix.setOrtho(-1, 1, -1, 1, g_near, g_far);
//将视图矩阵传递给u_ViewMatrix变量
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);
gl.clear(gl.COlOR_BUFFER_BIT);
console.log('near: ' + Math.round(g_near * 100)/100 + ', far: ' + Math.round(g_far * 100)/100)
gl.drawArrays(gl.TRIANGLES, 0, n);
}
透视投影
平行的视角看过去,物体没有那么真实,我们真实看到的世界一定是远小近大的,而不是平行的。透视投影也会有可视空间,同样的处于可视空间内的物体才会被显示出来。
但是透视投影近裁剪面比远裁剪面小,链接视点、近裁剪面、远裁剪面就会形成一个夹角,所以我们在定义透视投影时,一般使用,视角的夹角、近裁剪面的宽高比,视角距离近裁剪面和远裁剪面的距离
三个一样大小的三角形,从视角上看远近不同,大小也就不同,所以透视投影更贴近我们的视觉直观感受
var VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjMatrix;
varying vec4 v_Color;
void main() {
gl_Position = u_ProjMatrix * u_ViewMatrix * a_Position;
gl_PointSize = 10.0;
v_Color = a_Color;
}
`;
var FSHADER_SOURCE = `
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;
var gl = canvas.getContext('webgl');
initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)
this.gl = gl;
var n = this.initVertexBuffers(gl)
var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');
//设置视点、视线、上方向
var viewMatrix = new Matrix4();
viewMatrix.setLookAt(0, 0, 5, 0, 0, -100, 0, 1, 0);
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);
var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
var projMatrix = new Matrix4();
projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, n);
initVertexBuffers(gl){
var verticesColors = new Float32Array(
[
// Three triangles on the right side
0.75, 1.0, -4.0, 0.4, 1.0, 0.4, // The back green one
0.25, -1.0, -4.0, 0.4, 1.0, 0.4,
1.25, -1.0, -4.0, 1.0, 0.4, 0.4,
0.75, 1.0, -2.0, 1.0, 1.0, 0.4, // The middle yellow one
0.25, -1.0, -2.0, 1.0, 1.0, 0.4,
1.25, -1.0, -2.0, 1.0, 0.4, 0.4,
0.75, 1.0, 0.0, 0.4, 0.4, 1.0, // The front blue one
0.25, -1.0, 0.0, 0.4, 0.4, 1.0,
1.25, -1.0, 0.0, 1.0, 0.4, 0.4,
// Three triangles on the left side
-0.75, 1.0, -4.0, 0.4, 1.0, 0.4, // The back green one
-1.25, -1.0, -4.0, 0.4, 1.0, 0.4,
-0.25, -1.0, -4.0, 1.0, 0.4, 0.4,
-0.75, 1.0, -2.0, 1.0, 1.0, 0.4, // The middle yellow one
-1.25, -1.0, -2.0, 1.0, 1.0, 0.4,
-0.25, -1.0, -2.0, 1.0, 0.4, 0.4,
-0.75, 1.0, 0.0, 0.4, 0.4, 1.0, // The front blue one
-1.25, -1.0, 0.0, 0.4, 0.4, 1.0,
-0.25, -1.0, 0.0, 1.0, 0.4, 0.4,
]);
var n = 18; //点的个数
//创建缓冲区对象
var verteColorBuffer = gl.createBuffer();
if (!verteColorBuffer) {
console.log("Failed to create thie buffer object");
return -1;
}
//将缓冲区对象保存到目标上
gl.bindBuffer(gl.ARRAY_BUFFER, verteColorBuffer);
//向缓存对象写入数据
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log("Failed to get the storage location of a_Position");
return -1;
}
//将缓冲区对象分配给a_Postion变量
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE *6, 0);
//连接a_Postion变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
if (a_Color < 0) {
console.log("Failed to get the storage location of a_Position");
return -1;
}
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
gl.enableVertexAttribArray(a_Color);
gl.bindBuffer(gl.ARRAY_BUFFER, null);//取消绑定的缓冲区对象
return n;
}
层级关系
正常情况下 webgl 会根据先设置的图形挡住后面的图形,这是为了提高渲染效率,所以不会是离我们视点近的物体遮挡距离远的物体。
webgl 提供了隐藏面消除来解决这个问题。开启隐藏面消除,消除之后就会按照位置放置遮挡位置而不是先后顺序
gl.enable(gl.DEPTH_TEST)
gl.clear(gl.COLOR_BUFFER_BIT);