/**
* Object "tsuda" for "Computer Graphics"
*/
var tsuda = {};
tsuda.initWebGL = function(id,vshader_src,fshader_src) {
tsuda.canvas = document.getElementById(id);
if (!tsuda.canvas || !tsuda.canvas.getContext) {
console.log("canvas not supported"); return null;
}
tsuda.gl = getWebGLContext(tsuda.canvas);
if (! tsuda.gl) {
console.log("cannot get WebGL Context"); return null;
}
if (!initShaders(tsuda.gl,vshader_src,fshader_src)) {
console.log("cannot initiate shader"); return null;
}
return tsuda;
};
tsuda.initArrayBuffer = function (a_name,data,num,type) {
var buffer = tsuda.gl.createBuffer();
if (! buffer) {
console.log('failed to carete buffer object'); return null;
}
tsuda.gl.bindBuffer(tsuda.gl.ARRAY_BUFFER, buffer);
tsuda.gl.bufferData(tsuda.gl.ARRAY_BUFFER, data, tsuda.gl.STATIC_DRAW);
var aloc = tsuda.gl.getAttribLocation(tsuda.gl.program,a_name);
if (aloc < 0) {
console.log('failed to get location of ' + a_name); return null;
}
tsuda.gl.vertexAttribPointer(aloc,num,type,false,0,0);
tsuda.gl.enableVertexAttribArray(aloc);
tsuda.gl.bindBuffer(tsuda.gl.ARRAY_BUFFER, null);
return true;
};
tsuda.setArrayBuffer = function (data) {
if (data == null) { tsuda.gl.bindBuffer(tsuda.gl.ARRAY_BUFFER,null); return; }
var buffer = tsuda.gl.createBuffer();
if (! buffer) {
console.log('failed to carete buffer object');
return null;
}
tsuda.gl.bindBuffer(tsuda.gl.ARRAY_BUFFER, buffer);
tsuda.gl.bufferData(tsuda.gl.ARRAY_BUFFER, data, tsuda.gl.STATIC_DRAW);
return buffer;
};
tsuda.setAttributeVariable = function (a_name,size,type,stride,offset) {
var aloc = tsuda.gl.getAttribLocation(tsuda.gl.program,a_name);
if (aloc < 0) {
console.log('failed to get location of ' + a_name); return null;
}
tsuda.gl.vertexAttribPointer(aloc,size,type,false,stride,offset);
tsuda.gl.enableVertexAttribArray(aloc);
return aloc;
};
tsuda.setElementArrayBuffer = function (data) {
if (data == null) { tsuda.gl.bindBuffer(tsuda.gl.ELEMENT_ARRAY_BUFFER,null); return; }
var buffer = tsuda.gl.createBuffer();
if (! buffer) {
console.log('failed to carete buffer object'); return null;
}
tsuda.gl.bindBuffer(tsuda.gl.ELEMENT_ARRAY_BUFFER, buffer);
tsuda.gl.bufferData(tsuda.gl.ELEMENT_ARRAY_BUFFER, data, tsuda.gl.STATIC_DRAW);
return buffer;
};
/**
* new Float32Array([r, g, b, r, g, b, ...])
* @param r, g, b: float value
* @param n: Length of array is n*3
* @return Float32Array
*/
tsuda.get3Float32Array = function(r,g,b,n) {
var c = new Float32Array(n*3);
var i;
for (i=0; i<n; i++) { c[i*3+0]=r; c[i*3+1]=g; c[i*3+2]=b; }
return c;
};
/**
* Normal Vectors (each vertex is contained by one triangle)
* @param vertices: flat array of vertice
* @param stride: size of information of a vertex
* @param offset: offset to position data
* @return Float32Array
*/
tsuda.normals = function(vertices,stride,offset) {
if (stride == undefined || stride == 0) stride = 3;
if (offset == undefined) offset = 0;
var nV = vertices.length / stride; // number of vertices
var nF = nV / 3; // number of triangles
var ans = new Float32Array(nV*3); // normal vectors
var i;
for (i=0; i<nF; i++) {
var ai = 3*i, bi = 3*i + 1, ci = 3*i + 2; // index of vertices
var ap=ai*stride+offset, bp=bi*stride+offset, cp=ci*stride+offset;
var ax=vertices[ap+0], ay=vertices[ap+1], az=vertices[ap+2];
var bx=vertices[bp+0], by=vertices[bp+1], bz=vertices[bp+2];
var cx=vertices[cp+0], cy=vertices[cp+1], cz=vertices[cp+2];
var n = tsuda.normalVector(ax,ay,az,bx,by,bz,cx,cy,cz);
ans[ai*3+0] = ans[bi*3+0] = ans[ci*3+0] = n[0]; // x
ans[ai*3+1] = ans[bi*3+1] = ans[ci*3+1] = n[1]; // y
ans[ai*3+2] = ans[bi*3+2] = ans[ci*3+2] = n[2]; // z
}
return ans;
};
/**
* Normal Vectors (average of normal vectors of the vertex's adjacent triangles)
* @param vertices: flat array of vertice
* @param indices: flat array of indices
* @param stride: size of one vertex information
* @param offset: offset to position data in one vertex information
* @return Float32Array
*/
tsuda.indexNormals = function(vertices,indices,stride,offset) {
if (stride == undefined || stride == 0) stride = 3;
if (offset == undefined) offset = 0;
var nV = vertices.length / stride; // number of vertices
var nF = indices.length / 3; // number of triangles
var vNormals = []; // normal vectors of vertices
var count = []; // number of triangles which contain the vertex
var i;
for (i = 0; i < nV; i++) {
vNormals[i] = [0,0,0];
count[i] = 0;
}
for (i = 0; i < nF; i++) {
var ai = indices[i*3+0], bi = indices[i*3+1], ci = indices[i*3+2];
var ap = ai*stride+offset, bp=bi*stride+offset, cp=ci*stride+offset;
var ax = vertices[ap+0], ay = vertices[ap+1], az = vertices[ap+2];
var bx = vertices[bp+0], by = vertices[bp+1], bz = vertices[bp+2];
var cx = vertices[cp+0], cy = vertices[cp+1], cz = vertices[cp+2];
var n = tsuda.normalVector(ax,ay,az,bx,by,bz,cx,cy,cz);
vNormals[ai] = tsuda.vadd(vNormals[ai],n); count[ai]++;
vNormals[bi] = tsuda.vadd(vNormals[bi],n); count[bi]++;
vNormals[ci] = tsuda.vadd(vNormals[ci],n); count[ci]++;
}
var ans = new Float32Array(nV*3);
for (i = 0; i < nV; i++) {
vNormals[i] = tsuda.vscale(vNormals[i],1/count[i]);
ans[3*i+0] = vNormals[i][0];
ans[3*i+1] = vNormals[i][1];
ans[3*i+2] = vNormals[i][2];
}
return ans;
};
/**
* Normal Vector
* @param ax, ay, az: vector a
* @param bx, by, bz: vector b
* @param cx, cy, cz: vector c
* @return Array of float
*/
tsuda.normalVector = function(ax,ay,az,bx,by,bz,cx,cy,cz) {
if (arguments.length == 3) // ax, ay, ax: vector
return tsuda.normalVector(ax[0],ax[1],ax[2],ay[0],ay[1],ay[2],az[0],az[1],az[2]);
var v = tsuda.vsub(ax,ay,az,bx,by,bz);
var u = tsuda.vsub(ax,ay,az,cx,cy,cz);
var n = tsuda.vcross(v,u);
var len = tsuda.vlength(n);
n = tsuda.vscale(n,1/len);
return n;
};
/**
* Cross product
* @param vx, vy, vz: vector v
* @param ux, uy, uv: vecotr u
* @return Array of float
*/
tsuda.vcross = function(vx,vy,vz,ux,uy,uz) {
if (arguments.length == 2) // vx, vy: vector
return tsuda.vcross(vx[0],vx[1],vx[2],vy[0],vy[1],vy[2]);
var p = [];
p[0] = vy * uz - vz * uy;
p[1] = vz * ux - vx * uz;
p[2] = vx * uy - vy * ux;
return p;
};
/**
* Dot product
* @param vx, vy, vz: vector v
* @param ux, uy, uv: vecotr u
* @return float
*/
tsuda.vdot = function(vx,vy,vz,ux,uy,uz) {
if (arguments.length == 2) // vx, vy: vector
return tsuda.vdot(vx[0],vx[1],vx[2],vy[0],vy[1],vy[2]);
return vx * ux + vy * uy + vz * uz;
};
/**
* Vector Length
* @param x, y, z: vector
* @return float
*/
tsuda.vlength = function(x,y,z) {
if (arguments.length == 1) return tsuda.vlength(x[0],x[1],x[2]); //x: vector
return Math.sqrt(tsuda.vdot(x,y,z,x,y,z));
};
/**
* Vector Add
* @param vx, vy, vz: vector v
* @param ux, uy, uv: vecotr u
* @return Array of float
*/
tsuda.vadd = function(vx,vy,vz,ux,uy,uz) {
if (arguments.length == 2) // vx, vy: vector
return tsuda.vadd(vx[0],vx[1],vx[2],vy[0],vy[1],vy[2]);
var p = [];
p[0] = vx + ux;
p[1] = vy + uy;
p[2] = vz + uz;
return p;
};
/**
* Vector Subtract
* @param vx, vy, vz: vector v
* @param ux, uy, uv: vecotr u
* @return Array of float
*/
tsuda.vsub = function(vx,vy,vz,ux,uy,uz) {
if (arguments.length == 2) // vx, vy: vector
return tsuda.vsub(vx[0],vx[1],vx[2],vy[0],vy[1],vy[2]);
var p = [];
p[0] = vx - ux;
p[1] = vy - uy;
p[2] = vz - uz;
return p;
};
/**
* Vector Scale
* @param vx, vy, vz: vector v
* @param s: float
* @return Array of float
*/
tsuda.vscale = function(vx,vy,vz,s) {
if (arguments.length == 2) // vx:vector, vy:float
return tsuda.vscale(vx[0],vx[1],vx[2],vy);
var p = [];
p[0] = vx * s;
p[1] = vy * s;
p[2] = vz * s;
return p;
};
/**
* str
* @param vx,vy,vz: vector v
* @return String
*/
tsuda.vstr = function(vx,vy,vz) {
if (arguments.length == 1)
return tsuda.vstr(vx[0],vx[1],vx[2]);
else if (arguments.length == 2)
return tsuda.vstr(vx[vy+0],vx[vy+1],vx[vy+2]);
return vx+" "+vy+" "+vz;
};
/**
* Data
*/
// v6----- v5
// /| /|
// v1------v0|
// | | | |
// | |v7---|-|v4
// |/ |/
// v2------v3
tsuda.cube = {};
tsuda.cube.vertices = new Float32Array([
// x, y, z
1.0, 1.0, 1.0, // 0 v0 :front
-1.0, 1.0, 1.0, // 1 v1
-1.0, -1.0, 1.0, // 2 v2
1.0, -1.0, 1.0, // 3 v3
1.0, 1.0, 1.0, // 4 v0 :right
1.0, -1.0, 1.0, // 5 v3
1.0, -1.0, -1.0, // 6 v4
1.0, 1.0, -1.0, // 7 v5
1.0, 1.0, -1.0, // 8 v5 :back
1.0, -1.0, -1.0, // 9 v4
-1.0, -1.0, -1.0, //10 v7
-1.0, 1.0, -1.0, //11 v6
-1.0, 1.0, 1.0, //12 v1 :left
-1.0, 1.0, -1.0, //13 v6
-1.0, -1.0, -1.0, //14 v7
-1.0, -1.0, 1.0, //15 v2
1.0, 1.0, 1.0, //16 v0 :top
1.0, 1.0, -1.0, //17 v5
-1.0, 1.0, -1.0, //18 v6
-1.0, 1.0, 1.0, //19 v1
-1.0, -1.0, 1.0, //20 v2 :bottom
-1.0, -1.0, -1.0, //21 v7
1.0, -1.0, -1.0, //22 v4
1.0, -1.0, 1.0 //23 v3
]);
tsuda.cube.indices = new Uint8Array([
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // right
8, 9,10, 8,10,11, // back
12,13,14, 12,14,15, // left
16,17,18, 16,18,19, // top
20,21,22, 20,22,23 // bottom
]);
tsuda.cube.texCoord = new Float32Array([
1.0, 1.0, // v0 :front
0.0, 1.0, // v1
0.0, 0.0, // v2
1.0, 0.0, // v3
0.0, 1.0, // v0 :right
0.0, 0.0, // v3
1.0, 0.0, // v4
1.0, 1.0, // v5
0.0, 1.0, // v5 :back
0.0, 0.0, // v4
1.0, 0.0, // v7
1.0, 1.0, // v6
1.0, 1.0, // v1 :left
0.0, 1.0, // v6
0.0, 0.0, // v7
1.0, 0.0, // v2
1.0, 0.0, // v0 :top
1.0, 1.0, // v5
0.0, 1.0, // v6
0.0, 0.0, // v1
0.0, 1.0, // v2 :bottom
0.0, 0.0, // v7
1.0, 0.0, // v4
1.0, 1.0, // v3
]);
// v0\
// // | \
// | /v4--\--\v3
// |/ |/
// v1------v2
tsuda.pyramid = {};
tsuda.pyramid.vertices = new Float32Array([
// x, y, z, r, g, b
0.0, 2.0, 0.0, // 0 v0 :front
1.0, 0.0, 1.0, // 1 v1
1.0, 0.0, -1.0, // 2 v2
0.0, 2.0, 0.0, // 3 v0 :right
1.0, 0.0, -1.0, // 4 v2
-1.0, 0.0, -1.0, // 5 v3
0.0, 2.0, 0.0, // 6 v0 :back
-1.0, 0.0, -1.0, // 7 v3
-1.0, 0.0, 1.0, // 8 v4
0.0, 2.0, 0.0, // 9 v0 :left
-1.0, 0.0, 1.0, //10 v4
1.0, 0.0, 1.0, //11 v1
1.0, 0.0, 1.0, //12 v1 :bottom
-1.0, 0.0, 1.0, //13 v4
-1.0, 0.0, -1.0, //14 v3
1.0, 0.0, -1.0 //15 v2
]);
tsuda.pyramid.indices = new Uint8Array([
0, 1, 2, // forward
3, 4, 5, // right
6, 7, 8, // back
9,10,11, // left
12,13,14, 12,14,15 // bottom
]);
tsuda.pyramid.texCoord = new Float32Array([
0.5, 1.0, // v0 :front
0.0, 0.0, // v1
1.0, 0.0, // v2
0.5, 1.0, // v0 :right
0.0, 0.0, // v2
1.0, 0.0, // v3
0.5, 1.0, // v0 :back
0.0, 0.0, // v3
1.0, 0.0, // v4
0.5, 1.0, // v0 :left
0.0, 0.0, // v3
1.0, 0.0, // v4
0.0, 1.0, // v1 :bottom
0.0, 0.0, // v4
1.0, 0.0, // v3
1.0, 1.0 // v2
]);
|