上图,左图为一个球体的三维图,其中一个圆面以θ角(范围为[0,PI])的方式确定,该圆面在x-z坐标平面投影如右图,其中圆面上任意一点又由α确定(范围为[0,2PI])。
假定该球体半径为r,那么球面任意一点均可以用r,θ,α唯一确定,确定关系如下:
x=rsinθcosα;y=rcosθ;z=rsinθsinα
。
那么,可以将θ,α,均分为S+1份(也可以分别是不同的份数),然后可以得到(S+1)×(S+1)个点的坐标。
var SPHERE_DIV = 13; var i, ai, si, ci; var j, aj, sj, cj; var p1, p2; var positions = []; var indices = []; // Generate coordinates for (j = 0; j <= SPHERE_DIV; j++) { aj = j * Math.PI / SPHERE_DIV; sj = Math.sin(aj); cj = Math.cos(aj); for (i = 0; i <= SPHERE_DIV; i++) { ai = i * 2 * Math.PI / SPHERE_DIV; si = Math.sin(ai); ci = Math.cos(ai); positions.push(si * sj); // X positions.push(cj); // Y positions.push(ci * sj); // Z } }
右边是从左边网格抽象出来的单个网格单元,记左上角P1的位置为(i,j),那么P1的值为jX(S+1)+i,而P2的值为P1+(S+1),注意该单个网格由于在(i,j)的位置,都可以确定P2以及P1+1,P2+1,剩余三个点,而这三个点都是i,j的下一轮,所以在取得索引值时候,上界均为S-1,而非S,绘制时候,选择gl.TRIANGLE,所以每次取到的索引号是(p1,p2,p1+1,p1+1,p2,p2+1)。
for (j = 0; j < SPHERE_DIV; j++) { for (i = 0; i < SPHERE_DIV; i++) { p1 = j * (SPHERE_DIV+1) + i; p2 = p1 + (SPHERE_DIV+1); indices.push(p1); indices.push(p2); indices.push(p1 + 1); indices.push(p1 + 1); indices.push(p2); indices.push(p2 + 1); }