Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Carla-de-Beer
Last active December 26, 2020 21:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Carla-de-Beer/10ad7c7309fad48d94df to your computer and use it in GitHub Desktop.
Save Carla-de-Beer/10ad7c7309fad48d94df to your computer and use it in GitHub Desktop.
WebGL files
var canvas;
var gl;
// Cube
var pointsC = [];
var colorsC = [];
// Tetra
var pointsT = [];
var colorsT = [];
// Octo
var pointsO = [];
var colorsO = [];
// Axes: 0 = x; 1 = y; 3 = z
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
// Array of angles: 0 = x; 1 = y; 3 = z
var theta = [ 0, 0, 0 ];
var thetaLoc;
window.onload = function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL is not available" ); }
// --------------- Cube --------------------------
colorCube();
// --------------- Tetrahedron -------------------
colorTetra();
// --------------- Octohedron --------------------
colorOcto();
// viewport = rectangular area of display window
gl.viewport( 0, 0, canvas.width, canvas.height );
// clear area of display for rendering at each frame
gl.clearColor( 0.1, 0.1, 0.1, 1.0 );
gl.enable(gl.DEPTH_TEST);
// --------------- Load shaders and initialize attribute buffers
// --------------- Cube --------------------------
// Create a buffer object, initialise it, and associate it
// with the associated attribute variable in our vertex shader
var programCube = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( programCube );
// Buffer
var ccBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, ccBuffer );
gl.bufferData( gl.ARRAY_BUFFER, transpose(colorsC), gl.STATIC_DRAW );
// Cube colour; set attributes
var cvColor = gl.getAttribLocation( programCube, "vColor" );
gl.vertexAttribPointer( cvColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( cvColor );
// Cube create points buffer
var cvBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cvBuffer );
gl.bufferData( gl.ARRAY_BUFFER, transpose(pointsC), gl.STATIC_DRAW );
// Cube create position
var cvPosition = gl.getAttribLocation( programCube, "vPosition" );
gl.vertexAttribPointer( cvPosition, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( cvPosition );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
thetaLoc = gl.getUniformLocation(programCube, "theta");
//gl.drawArrays( gl.TRIANGLES, 0, pointsC.length );
gl.uniform3fv(thetaLoc, theta);
render();
// --------------- Tetrahedron -------------------
// Create a buffer object, initialise it, and associate it
// with the associated attribute variable in our vertex shader
var programTetra = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( programTetra );
var tcBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, tcBuffer );
gl.bufferData( gl.ARRAY_BUFFER, transpose(colorsT), gl.STATIC_DRAW );
var tvColor = gl.getAttribLocation( programTetra, "vColor" );
gl.vertexAttribPointer( tvColor, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( tvColor );
var tvBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, tvBuffer);
gl.bufferData( gl.ARRAY_BUFFER, transpose(pointsT), gl.STATIC_DRAW );
var tvPosition = gl.getAttribLocation( programTetra, "vPosition" );
gl.vertexAttribPointer( tvPosition, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( tvPosition );
//thetaLoc = gl.getUniformLocation(programTetra, "theta");
gl.drawArrays( gl.TRIANGLES, 0, pointsT.length );
// --------------- Octohedron --------------------
// Create a buffer object, initialise it, and associate it
// with the associated attribute variable in our vertex shader
var programOcto = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( programOcto );
var ocBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, ocBuffer );
gl.bufferData( gl.ARRAY_BUFFER, transpose(colorsO), gl.STATIC_DRAW );
var ovColor = gl.getAttribLocation( programOcto, "vColor" );
gl.vertexAttribPointer( ovColor, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( ovColor );
var ovBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, ovBuffer );
gl.bufferData( gl.ARRAY_BUFFER, transpose(pointsO), gl.STATIC_DRAW );
var ovPosition = gl.getAttribLocation( programOcto, "vPosition" );
gl.vertexAttribPointer( ovPosition, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( ovPosition );
//thetaLoc = gl.getUniformLocation(programOcto, "theta");
gl.drawArrays( gl.TRIANGLES, 0, pointsO.length );
// ------------------------------------------------------------------
// Event listeners for buttons
var isZ = false;
var isY = false;
var isX = false;
document.getElementById( "xRot" ).onclick = function() {
axis = xAxis;
isX = !isX;
document.getElementById('xRot').style.background='#bebfba';
if(!isX){
document.getElementById('xRot').style.background='#FFF';
}
};
document.getElementById( "yRot" ).onclick = function() {
axis = yAxis;
isY = !isY;
document.getElementById('yRot').style.background='#bebfba';
if(!isY){
document.getElementById('yRot').style.background='#FFF';
}
};
document.getElementById( "zRot" ).onclick = function() {
axis = zAxis;
isZ = !isZ;
document.getElementById('zRot').style.background='#bebfba';
if(!isZ){
document.getElementById('zRot').style.background='#FFF';
}
};
}
// -------------------------------------------------------------------
function render()
{
theta[axis] += 2.0;
gl.uniform3fv(thetaLoc, theta);
// Render cube
gl.drawArrays( gl.TRIANGLES, 0, pointsC.length );
requestAnimationFrame( render );
}
// DEFINE CUBE
function colorCube()
{
square( 1, 0, 3, 2 );
square( 2, 3, 7, 6 );
square( 3, 0, 4, 7 );
square( 6, 5, 1, 2 );
square( 4, 5, 6, 7 );
square( 5, 4, 0, 1 );
}
function square(a, b, c, d)
{
var verticesC = [
vec3( -0.25, -0.25, 0.25 ),
vec3( -0.25, 0.25, 0.25 ),
vec3( 0.25, 0.25, 0.25 ),
vec3( 0.25, -0.25, 0.25 ),
vec3( -0.25, -0.25, -0.25 ),
vec3( -0.25, 0.25, -0.25 ),
vec3( 0.25, 0.25, -0.25 ),
vec3( 0.25, -0.25, -0.25 )
];
var vertexColors = [
[ 0.9, 0.9, 0.2, 1.0 ], // orange
[ 0.0, 1.0, 1.0, 1.0 ], // cyan
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ], // green
[ 1.0, 0.0, 1.0, 1.0 ], // magenta
[ 0.0, 0.0, 1.0, 1.0 ], // blue
[ 1.0, 1.0, 1.0, 1.0 ] // white
];
// Partion the square into two triangles in order for
// WebGL to be able to render it.
// Vertex color assigned by the index of the vertex
var indices = [ a, b, c, a, c, d ];
for ( var i = 0; i < indices.length; ++i ) {
pointsC.push( verticesC[indices[i]] );
colorsC.push( vertexColors[indices[i]] );
//for solid colored faces use
//colorsC.push(vertexColors[a]);
}
}
// DEFINE TETRAHEDRON
function colorTetra(){
var verticesT = [
vec3( 0.0000, 0.0000, -0.3500 ),
vec3( 0.0000, 0.3500, 0.1500 ),
vec3( -0.3500, -0.1500, 0.1500 ),
vec3( 0.3500, -0.1500, 0.1500 )
];
tetra(verticesT[0], verticesT[1], verticesT[2], verticesT[3]);
}
function makeTetra( a, b, c, color )
{
// add colors and vertices for one triangle
var baseColors = [
vec3(0.7, 0.7, 0.9, 1.0),
vec3(0.6, 0.8, 0.9, 1.0),
vec3(0.5, 0.6, 0.9, 1.0),
vec3(1.0, 1.0, 0.2, 1.0)
];
colorsT.push( baseColors[color] );
pointsT.push( a );
colorsT.push( baseColors[color] );
pointsT.push( b );
colorsT.push( baseColors[color] );
pointsT.push( c );
}
function tetra( p, q, r, s )
{
// tetrahedron with each side using
// a different color
makeTetra( p, r, q, 0 );
makeTetra( p, r, s, 1 );
makeTetra( p, q, s, 2 );
makeTetra( q, r, s, 3 );
}
// DEFINE OCTOHEDRON
function colorOcto(){
var verticesO = [
vec3( 0.4000, 0.0000, 0.0000 ),
vec3( 0.0000, 0.0000, 0.0000 ),
vec3( 0.0000, 0.4000, 0.0000 ),
vec3( 0.4000, 0.4000, 0.0000 ),
vec3( 0.2000, 0.2000, 0.3000 ),
vec3( 0.2000, 0.2000, -0.3000 )
];
octo(verticesO[0], verticesO[1], verticesO[2], verticesO[3], verticesO[4], verticesO[5]);
}
function makeOcto( a, b, c, color )
{
// add colors and vertices for one triangle
var baseColors = [
vec3(0.6, 0.6, 0.6, 1.0),
vec3(0.3, 0.4, 0.9, 1.0),
vec3(0.9, 0.9, 0.9, 1.0),
];
colorsO.push( baseColors[color] );
pointsO.push( a );
colorsO.push( baseColors[color] );
pointsO.push( b );
colorsO.push( baseColors[color] );
pointsO.push( c );
}
function octo( a, b, c, d , e, f)
{
// tetrahedron with each side using
// a different color
makeOcto( a, d, e, 0 );
makeOcto( a, b, e, 1 );
makeOcto( b, c, e, 0 );
makeOcto( c, d, e, 1 );
makeOcto( a, d, f, 1 );
makeOcto( a, b, f, 2 );
makeOcto( b, c, f, 1 );
makeOcto( c, d, f, 2 );
}
<html>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
// The matrices are column-major
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, s.x, 0.0,
0.0, -s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0,
s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
fColor = vColor;
gl_Position = rz * ry * rx * vPosition;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<script type="text/javascript" src="webgl-utils.js"></script>
<script type="text/javascript" src="initShaders.js"></script>
<script type="text/javascript" src="MV.js"></script>
<script type="text/javascript" src="cube.js"></script>
<body>
<canvas id="gl-canvas" width="725"" height="725">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<br>
<button id="xButton" style="background: #FFF">Rotate X</button>
<button id="yButton" style="background: #FFF">Rotate Y</button>
<button id="zButton" style="background: #FFF">Rotate Z</button>
</body>
</html>
function initShaders( gl, vertexShaderId, fragmentShaderId )
{
var vertShdr;
var fragShdr;
var vertElem = document.getElementById( vertexShaderId );
if ( !vertElem ) {
alert( "Unable to load vertex shader " + vertexShaderId );
return -1;
}
else {
vertShdr = gl.createShader( gl.VERTEX_SHADER );
gl.shaderSource( vertShdr, vertElem.text );
gl.compileShader( vertShdr );
if ( !gl.getShaderParameter(vertShdr, gl.COMPILE_STATUS) ) {
var msg = "Vertex shader failed to compile. The error log is:"
+ "<pre>" + gl.getShaderInfoLog( vertShdr ) + "</pre>";
alert( msg );
return -1;
}
}
var fragElem = document.getElementById( fragmentShaderId );
if ( !fragElem ) {
alert( "Unable to load vertex shader " + fragmentShaderId );
return -1;
}
else {
fragShdr = gl.createShader( gl.FRAGMENT_SHADER );
gl.shaderSource( fragShdr, fragElem.text );
gl.compileShader( fragShdr );
if ( !gl.getShaderParameter(fragShdr, gl.COMPILE_STATUS) ) {
var msg = "Fragment shader failed to compile. The error log is:"
+ "<pre>" + gl.getShaderInfoLog( fragShdr ) + "</pre>";
alert( msg );
return -1;
}
}
var program = gl.createProgram();
gl.attachShader( program, vertShdr );
gl.attachShader( program, fragShdr );
gl.linkProgram( program );
if ( !gl.getProgramParameter(program, gl.LINK_STATUS) ) {
var msg = "Shader program failed to link. The error log is:"
+ "<pre>" + gl.getProgramInfoLog( program ) + "</pre>";
alert( msg );
return -1;
}
return program;
}
//----------------------------------------------------------------------------
//
// Helper functions
//
function _argumentsToArray( args )
{
return [].concat.apply( [], Array.prototype.slice.apply(args) );
}
//----------------------------------------------------------------------------
function radians( degrees ) {
return degrees * Math.PI / 180.0;
}
//----------------------------------------------------------------------------
//
// Vector Constructors
//
function vec2()
{
var result = _argumentsToArray( arguments );
switch ( result.length ) {
case 0: result.push( 0.0 );
case 1: result.push( 0.0 );
}
return result.splice( 0, 2 );
}
function vec3()
{
var result = _argumentsToArray( arguments );
switch ( result.length ) {
case 0: result.push( 0.0 );
case 1: result.push( 0.0 );
case 2: result.push( 0.0 );
}
return result.splice( 0, 3 );
}
function vec4()
{
var result = _argumentsToArray( arguments );
switch ( result.length ) {
case 0: result.push( 0.0 );
case 1: result.push( 0.0 );
case 2: result.push( 0.0 );
case 3: result.push( 1.0 );
}
return result.splice( 0, 4 );
}
//----------------------------------------------------------------------------
//
// Matrix Constructors
//
function mat2()
{
var v = _argumentsToArray( arguments );
var m = [];
switch ( v.length ) {
case 0:
v[0] = 1;
case 1:
m = [
vec2( v[0], 0.0 ),
vec2( 0.0, v[0] )
];
break;
default:
m.push( vec2(v) ); v.splice( 0, 2 );
m.push( vec2(v) );
break;
}
m.matrix = true;
return m;
}
//----------------------------------------------------------------------------
function mat3()
{
var v = _argumentsToArray( arguments );
var m = [];
switch ( v.length ) {
case 0:
v[0] = 1;
case 1:
m = [
vec3( v[0], 0.0, 0.0 ),
vec3( 0.0, v[0], 0.0 ),
vec3( 0.0, 0.0, v[0] )
];
break;
default:
m.push( vec3(v) ); v.splice( 0, 3 );
m.push( vec3(v) ); v.splice( 0, 3 );
m.push( vec3(v) );
break;
}
m.matrix = true;
return m;
}
//----------------------------------------------------------------------------
function mat4()
{
var v = _argumentsToArray( arguments );
var m = [];
switch ( v.length ) {
case 0:
v[0] = 1;
case 1:
m = [
vec4( v[0], 0.0, 0.0, 0.0 ),
vec4( 0.0, v[0], 0.0, 0.0 ),
vec4( 0.0, 0.0, v[0], 0.0 ),
vec4( 0.0, 0.0, 0.0, v[0] )
];
break;
default:
m.push( vec4(v) ); v.splice( 0, 4 );
m.push( vec4(v) ); v.splice( 0, 4 );
m.push( vec4(v) ); v.splice( 0, 4 );
m.push( vec4(v) );
break;
}
m.matrix = true;
return m;
}
//----------------------------------------------------------------------------
//
// Generic Mathematical Operations for Vectors and Matrices
//
function equal( u, v )
{
if ( u.length != v.length ) { return false; }
if ( u.matrix && v.matrix ) {
for ( var i = 0; i < u.length; ++i ) {
if ( u[i].length != v[i].length ) { return false; }
for ( var j = 0; j < u[i].length; ++j ) {
if ( u[i][j] !== v[i][j] ) { return false; }
}
}
}
else if ( u.matrix && !v.matrix || !u.matrix && v.matrix ) {
return false;
}
else {
for ( var i = 0; i < u.length; ++i ) {
if ( u[i] !== v[i] ) { return false; }
}
}
return true;
}
//----------------------------------------------------------------------------
function add( u, v )
{
var result = [];
if ( u.matrix && v.matrix ) {
if ( u.length != v.length ) {
throw "add(): trying to add matrices of different dimensions";
}
for ( var i = 0; i < u.length; ++i ) {
if ( u[i].length != v[i].length ) {
throw "add(): trying to add matrices of different dimensions";
}
result.push( [] );
for ( var j = 0; j < u[i].length; ++j ) {
result[i].push( u[i][j] + v[i][j] );
}
}
result.matrix = true;
return result;
}
else if ( u.matrix && !v.matrix || !u.matrix && v.matrix ) {
throw "add(): trying to add matrix and non-matrix variables";
}
else {
if ( u.length != v.length ) {
throw "add(): vectors are not the same dimension";
}
for ( var i = 0; i < u.length; ++i ) {
result.push( u[i] + v[i] );
}
return result;
}
}
//----------------------------------------------------------------------------
function subtract( u, v )
{
var result = [];
if ( u.matrix && v.matrix ) {
if ( u.length != v.length ) {
throw "subtract(): trying to subtract matrices" +
" of different dimensions";
}
for ( var i = 0; i < u.length; ++i ) {
if ( u[i].length != v[i].length ) {
throw "subtract(): trying to subtact matrices" +
" of different dimensions";
}
result.push( [] );
for ( var j = 0; j < u[i].length; ++j ) {
result[i].push( u[i][j] - v[i][j] );
}
}
result.matrix = true;
return result;
}
else if ( u.matrix && !v.matrix || !u.matrix && v.matrix ) {
throw "subtact(): trying to subtact matrix and non-matrix variables";
}
else {
if ( u.length != v.length ) {
throw "subtract(): vectors are not the same length";
}
for ( var i = 0; i < u.length; ++i ) {
result.push( u[i] - v[i] );
}
return result;
}
}
//----------------------------------------------------------------------------
function mult( u, v )
{
var result = [];
if ( u.matrix && v.matrix ) {
if ( u.length != v.length ) {
throw "mult(): trying to add matrices of different dimensions";
}
for ( var i = 0; i < u.length; ++i ) {
if ( u[i].length != v[i].length ) {
throw "mult(): trying to add matrices of different dimensions";
}
}
for ( var i = 0; i < u.length; ++i ) {
result.push( [] );
for ( var j = 0; j < v.length; ++j ) {
var sum = 0.0;
for ( var k = 0; k < u.length; ++k ) {
sum += u[i][k] * v[k][j];
}
result[i].push( sum );
}
}
result.matrix = true;
return result;
}
else {
if ( u.length != v.length ) {
throw "mult(): vectors are not the same dimension";
}
for ( var i = 0; i < u.length; ++i ) {
result.push( u[i] * v[i] );
}
return result;
}
}
//----------------------------------------------------------------------------
//
// Basic Transformation Matrix Generators
//
function translate( x, y, z )
{
if ( Array.isArray(x) && x.length == 3 ) {
z = x[2];
y = x[1];
x = x[0];
}
var result = mat4();
result[0][3] = x;
result[1][3] = y;
result[2][3] = z;
return result;
}
//----------------------------------------------------------------------------
function rotate( angle, axis )
{
if ( !Array.isArray(axis) ) {
axis = [ arguments[1], arguments[2], arguments[3] ];
}
var v = normalize( axis );
var x = v[0];
var y = v[1];
var z = v[2];
var c = Math.cos( radians(angle) );
var omc = 1.0 - c;
var s = Math.sin( radians(angle) );
var result = mat4(
vec4( x*x*omc + c, x*y*omc - z*s, x*z*omc + y*s, 0.0 ),
vec4( x*y*omc + z*s, y*y*omc + c, y*z*omc - x*s, 0.0 ),
vec4( x*z*omc - y*s, y*z*omc + x*s, z*z*omc + c, 0.0 ),
vec4()
);
return result;
}
//----------------------------------------------------------------------------
function scale( x, y, z )
{
if ( Array.isArray(x) && x.length == 3 ) {
z = x[2];
y = x[1];
x = x[0];
}
var result = mat4();
result[0][0] = x;
result[1][1] = y;
result[2][2] = z;
return result;
}
//----------------------------------------------------------------------------
//
// ModelView Matrix Generators
//
function lookAt( eye, at, up )
{
if ( !Array.isArray(eye) || eye.length != 3) {
throw "lookAt(): first parameter [eye] must be an a vec3";
}
if ( !Array.isArray(at) || at.length != 3) {
throw "lookAt(): first parameter [at] must be an a vec3";
}
if ( !Array.isArray(up) || up.length != 3) {
throw "lookAt(): first parameter [up] must be an a vec3";
}
if ( equal(eye, at) ) {
return mat4();
}
var v = normalize( subtract(at, eye) ); // view direction vector
var n = normalize( cross(v, up) ); // perpendicular vector
var u = normalize( cross(n, v) ); // "new" up vector
v = negate( v );
var result = mat4(
vec4( n, -dot(n, eye) ),
vec4( u, -dot(u, eye) ),
vec4( v, -dot(v, eye) ),
vec4()
);
return result;
}
//----------------------------------------------------------------------------
//
// Projection Matrix Generators
//
function ortho( left, right, bottom, top, near, far )
{
if ( left == right ) { throw "ortho(): left and right are equal"; }
if ( bottom == top ) { throw "ortho(): bottom and top are equal"; }
if ( near == far ) { throw "ortho(): near and far are equal"; }
var w = right - left;
var h = top - bottom;
var d = far - near;
var result = mat4();
result[0][0] = 2.0 / w;
result[1][1] = 2.0 / h;
result[2][2] = -2.0 / d;
result[0][3] = -(left + right) / w;
result[1][3] = -(top + bottom) / h;
result[2][3] = -(near + far) / d;
return result;
}
//----------------------------------------------------------------------------
function perspective( fovy, aspect, near, far )
{
var f = 1.0 / Math.tan( radians(fovy) / 2 );
var d = far - near;
var result = mat4();
result[0][0] = f / aspect;
result[1][1] = f;
result[2][2] = -(near + far) / d;
result[2][3] = -2 * near * far / d;
result[3][2] = -1;
result[3][3] = 0.0;
return result;
}
//----------------------------------------------------------------------------
//
// Matrix Functions
//
function transpose( m )
{
if ( !m.matrix ) {
return "transpose(): trying to transpose a non-matrix";
}
var result = [];
for ( var i = 0; i < m.length; ++i ) {
result.push( [] );
for ( var j = 0; j < m[i].length; ++j ) {
result[i].push( m[j][i] );
}
}
result.matrix = true;
return result;
}
//----------------------------------------------------------------------------
//
// Vector Functions
//
function dot( u, v )
{
if ( u.length != v.length ) {
throw "dot(): vectors are not the same dimension";
}
var sum = 0.0;
for ( var i = 0; i < u.length; ++i ) {
sum += u[i] * v[i];
}
return sum;
}
//----------------------------------------------------------------------------
function negate( u )
{
result = [];
for ( var i = 0; i < u.length; ++i ) {
result.push( -u[i] );
}
return result;
}
//----------------------------------------------------------------------------
function cross( u, v )
{
if ( !Array.isArray(u) || u.length < 3 ) {
throw "cross(): first argument is not a vector of at least 3";
}
if ( !Array.isArray(v) || v.length < 3 ) {
throw "cross(): second argument is not a vector of at least 3";
}
var result = [
u[1]*v[2] - u[2]*v[1],
u[2]*v[0] - u[0]*v[2],
u[0]*v[1] - u[1]*v[0]
];
return result;
}
//----------------------------------------------------------------------------
function length( u )
{
return Math.sqrt( dot(u, u) );
}
//----------------------------------------------------------------------------
function normalize( u, excludeLastComponent )
{
if ( excludeLastComponent ) {
var last = u.pop();
}
var len = length( u );
if ( !isFinite(len) ) {
throw "normalize: vector " + u + " has zero length";
}
for ( var i = 0; i < u.length; ++i ) {
u[i] /= len;
}
if ( excludeLastComponent ) {
u.push( last );
}
return u;
}
//----------------------------------------------------------------------------
function mix( u, v, s )
{
if ( typeof s !== "number" ) {
throw "mix: the last paramter " + s + " must be a number";
}
if ( u.length != v.length ) {
throw "vector dimension mismatch";
}
var result = [];
for ( var i = 0; i < u.length; ++i ) {
result.push( s * u[i] + (1.0 - s) * v[i] );
}
return result;
}
//----------------------------------------------------------------------------
//
// Vector and Matrix functions
//
function scale( s, u )
{
if ( !Array.isArray(u) ) {
throw "scale: second parameter " + u + " is not a vector";
}
result = [];
for ( var i = 0; i < u.length; ++i ) {
result.push( s * u[i] );
}
return result;
}
//----------------------------------------------------------------------------
//
//
//
function flatten( v )
{
if ( v.matrix === true ) {
v = transpose( v );
}
var n = v.length;
var elemsAreArrays = false;
if ( Array.isArray(v[0]) ) {
elemsAreArrays = true;
n *= v[0].length;
}
var floats = new Float32Array( n );
if ( elemsAreArrays ) {
var idx = 0;
for ( var i = 0; i < v.length; ++i ) {
for ( var j = 0; j < v[i].length; ++j ) {
floats[idx++] = v[i][j];
}
}
}
else {
for ( var i = 0; i < v.length; ++i ) {
floats[i] = v[i];
}
}
return floats;
}
//----------------------------------------------------------------------------
var sizeof = {
'vec2' : new Float32Array( flatten(vec2()) ).byteLength,
'vec3' : new Float32Array( flatten(vec3()) ).byteLength,
'vec4' : new Float32Array( flatten(vec4()) ).byteLength,
'mat2' : new Float32Array( flatten(mat2()) ).byteLength,
'mat3' : new Float32Array( flatten(mat3()) ).byteLength,
'mat4' : new Float32Array( flatten(mat4()) ).byteLength
};
/*
* Copyright 2010, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @fileoverview This file contains functions every webgl program will need
* a version of one way or another.
*
* Instead of setting up a context manually it is recommended to
* use. This will check for success or failure. On failure it
* will attempt to present an approriate message to the user.
*
* gl = WebGLUtils.setupWebGL(canvas);
*
* For animated WebGL apps use of setTimeout or setInterval are
* discouraged. It is recommended you structure your rendering
* loop like this.
*
* function render() {
* window.requestAnimFrame(render, canvas);
*
* // do rendering
* ...
* }
* render();
*
* This will call your rendering function up to the refresh rate
* of your display but will stop rendering if your app is not
* visible.
*/
WebGLUtils = function() {
/**
* Creates the HTLM for a failure message
* @param {string} canvasContainerId id of container of th
* canvas.
* @return {string} The html.
*/
var makeFailHTML = function(msg) {
return '' +
'<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' +
'<td align="center">' +
'<div style="display: table-cell; vertical-align: middle;">' +
'<div style="">' + msg + '</div>' +
'</div>' +
'</td></tr></table>';
};
/**
* Mesasge for getting a webgl browser
* @type {string}
*/
var GET_A_WEBGL_BROWSER = '' +
'This page requires a browser that supports WebGL.<br/>' +
'<a href="http://get.webgl.org">Click here to upgrade your browser.</a>';
/**
* Mesasge for need better hardware
* @type {string}
*/
var OTHER_PROBLEM = '' +
"It doesn't appear your computer can support WebGL.<br/>" +
'<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>';
/**
* Creates a webgl context. If creation fails it will
* change the contents of the container of the <canvas>
* tag to an error message with the correct links for WebGL.
* @param {Element} canvas. The canvas element to create a
* context from.
* @param {WebGLContextCreationAttirbutes} opt_attribs Any
* creation attributes you want to pass in.
* @return {WebGLRenderingContext} The created context.
*/
var setupWebGL = function(canvas, opt_attribs) {
function showLink(str) {
var container = canvas.parentNode;
if (container) {
container.innerHTML = makeFailHTML(str);
}
};
if (!window.WebGLRenderingContext) {
showLink(GET_A_WEBGL_BROWSER);
return null;
}
var context = create3DContext(canvas, opt_attribs);
if (!context) {
showLink(OTHER_PROBLEM);
}
return context;
};
/**
* Creates a webgl context.
* @param {!Canvas} canvas The canvas tag to get context
* from. If one is not passed in one will be created.
* @return {!WebGLContext} The created context.
*/
var create3DContext = function(canvas, opt_attribs) {
var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
var context = null;
for (var ii = 0; ii < names.length; ++ii) {
try {
context = canvas.getContext(names[ii], opt_attribs);
} catch(e) {}
if (context) {
break;
}
}
return context;
}
return {
create3DContext: create3DContext,
setupWebGL: setupWebGL
};
}();
/**
* Provides requestAnimationFrame in a cross browser way.
*/
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000/60);
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment