Last commit was foobar.
1.1 --- a/machine.html Fri Apr 01 01:45:39 2011 +0200
1.2 +++ b/machine.html Fri Apr 01 01:51:08 2011 +0200
1.3 @@ -0,0 +1,39 @@
1.4 +<html>
1.5 +<head>
1.6 +<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1.7 +<title>Machine Alpha</title>
1.8 +<script src="scripts/CanvasMatrix.js" type="text/javascript"> </script>
1.9 +<script src="scripts/utils3d.js" type="text/javascript"> </script>
1.10 +<script src="scripts/glMatrix.js" type="text/javascript"></script>
1.11 +
1.12 +<script id="fragment-shader" type="x-shader/x-fragment">
1.13 + #ifdef GL_ES
1.14 + precision highp float;
1.15 + #endif
1.16 +
1.17 + void main(void) {
1.18 + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
1.19 + }
1.20 +</script>
1.21 +
1.22 +<script id="vertex-shader" type="x-shader/x-vertex">
1.23 + attribute vec3 aVertexPosition;
1.24 +
1.25 + uniform mat4 uMVMatrix;
1.26 + uniform mat4 uPMatrix;
1.27 +
1.28 + void main(void) {
1.29 + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
1.30 + }
1.31 +</script>
1.32 +
1.33 +<script src="scripts/machine.js" type="text/javascript"></script>
1.34 +</head>
1.35 +
1.36 +<body onload="main();">
1.37 +<canvas id="machine">
1.38 + Download a browser with WebGL support, like Chrome or Firefox.
1.39 +</canvas>
1.40 +</body>
1.41 +
1.42 +</html>
2.1 --- a/scripts/CanvasMatrix.js Fri Apr 01 01:45:39 2011 +0200
2.2 +++ b/scripts/CanvasMatrix.js Fri Apr 01 01:51:08 2011 +0200
2.3 @@ -0,0 +1,698 @@
2.4 +/*
2.5 + CanvasMatrix4 class
2.6 +
2.7 + This class implements a 4x4 matrix. It has functions which
2.8 + duplicate the functionality of the OpenGL matrix stack and
2.9 + glut functions.
2.10 +
2.11 + IDL:
2.12 +
2.13 + [
2.14 + Constructor(in CanvasMatrix4 matrix), // copy passed matrix into new CanvasMatrix4
2.15 + Constructor(in sequence<float> array) // create new CanvasMatrix4 with 16 floats (row major)
2.16 + Constructor() // create new CanvasMatrix4 with identity matrix
2.17 + ]
2.18 + interface CanvasMatrix4 {
2.19 + attribute float m11;
2.20 + attribute float m12;
2.21 + attribute float m13;
2.22 + attribute float m14;
2.23 + attribute float m21;
2.24 + attribute float m22;
2.25 + attribute float m23;
2.26 + attribute float m24;
2.27 + attribute float m31;
2.28 + attribute float m32;
2.29 + attribute float m33;
2.30 + attribute float m34;
2.31 + attribute float m41;
2.32 + attribute float m42;
2.33 + attribute float m43;
2.34 + attribute float m44;
2.35 +
2.36 + void load(in CanvasMatrix4 matrix); // copy the values from the passed matrix
2.37 + void load(in sequence<float> array); // copy 16 floats into the matrix
2.38 + sequence<float> getAsArray(); // return the matrix as an array of 16 floats
2.39 + WebGLFloatArray getAsCanvasFloatArray(); // return the matrix as a WebGLFloatArray with 16 values
2.40 + void makeIdentity(); // replace the matrix with identity
2.41 + void transpose(); // replace the matrix with its transpose
2.42 + void invert(); // replace the matrix with its inverse
2.43 +
2.44 + void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right
2.45 + void scale(in float x, in float y, in float z); // multiply the matrix by passed scale values on the right
2.46 + void rotate(in float angle, // multiply the matrix by passed rotation values on the right
2.47 + in float x, in float y, in float z); // (angle is in degrees)
2.48 + void multRight(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the right
2.49 + void multLeft(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the left
2.50 + void ortho(in float left, in float right, // multiply the matrix by the passed ortho values on the right
2.51 + in float bottom, in float top,
2.52 + in float near, in float far);
2.53 + void frustum(in float left, in float right, // multiply the matrix by the passed frustum values on the right
2.54 + in float bottom, in float top,
2.55 + in float near, in float far);
2.56 + void perspective(in float fovy, in float aspect, // multiply the matrix by the passed perspective values on the right
2.57 + in float zNear, in float zFar);
2.58 + void lookat(in float eyex, in float eyey, in float eyez, // multiply the matrix by the passed lookat
2.59 + in float ctrx, in float ctry, in float ctrz, // values on the right
2.60 + in float upx, in float upy, in float upz);
2.61 + }
2.62 +*/
2.63 +
2.64 +CanvasMatrix4 = function(m)
2.65 +{
2.66 + if (typeof m == 'object') {
2.67 + if ("length" in m && m.length >= 16) {
2.68 + this.load(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
2.69 + return;
2.70 + }
2.71 + else if (m instanceof CanvasMatrix4) {
2.72 + this.load(m);
2.73 + return;
2.74 + }
2.75 + }
2.76 + this.makeIdentity();
2.77 +}
2.78 +
2.79 +CanvasMatrix4.prototype.load = function()
2.80 +{
2.81 + if (arguments.length == 1 && typeof arguments[0] == 'object') {
2.82 + var matrix = arguments[0];
2.83 +
2.84 + if ("length" in matrix && matrix.length == 16) {
2.85 + this.m11 = matrix[0];
2.86 + this.m12 = matrix[1];
2.87 + this.m13 = matrix[2];
2.88 + this.m14 = matrix[3];
2.89 +
2.90 + this.m21 = matrix[4];
2.91 + this.m22 = matrix[5];
2.92 + this.m23 = matrix[6];
2.93 + this.m24 = matrix[7];
2.94 +
2.95 + this.m31 = matrix[8];
2.96 + this.m32 = matrix[9];
2.97 + this.m33 = matrix[10];
2.98 + this.m34 = matrix[11];
2.99 +
2.100 + this.m41 = matrix[12];
2.101 + this.m42 = matrix[13];
2.102 + this.m43 = matrix[14];
2.103 + this.m44 = matrix[15];
2.104 + return;
2.105 + }
2.106 +
2.107 + if (arguments[0] instanceof CanvasMatrix4) {
2.108 +
2.109 + this.m11 = matrix.m11;
2.110 + this.m12 = matrix.m12;
2.111 + this.m13 = matrix.m13;
2.112 + this.m14 = matrix.m14;
2.113 +
2.114 + this.m21 = matrix.m21;
2.115 + this.m22 = matrix.m22;
2.116 + this.m23 = matrix.m23;
2.117 + this.m24 = matrix.m24;
2.118 +
2.119 + this.m31 = matrix.m31;
2.120 + this.m32 = matrix.m32;
2.121 + this.m33 = matrix.m33;
2.122 + this.m34 = matrix.m34;
2.123 +
2.124 + this.m41 = matrix.m41;
2.125 + this.m42 = matrix.m42;
2.126 + this.m43 = matrix.m43;
2.127 + this.m44 = matrix.m44;
2.128 + return;
2.129 + }
2.130 + }
2.131 +
2.132 + this.makeIdentity();
2.133 +}
2.134 +
2.135 +CanvasMatrix4.prototype.getAsArray = function()
2.136 +{
2.137 + return [
2.138 + this.m11, this.m12, this.m13, this.m14,
2.139 + this.m21, this.m22, this.m23, this.m24,
2.140 + this.m31, this.m32, this.m33, this.m34,
2.141 + this.m41, this.m42, this.m43, this.m44
2.142 + ];
2.143 +}
2.144 +
2.145 +CanvasMatrix4.prototype.getAsCanvasFloatArray = function()
2.146 +{
2.147 + return new WebGLFloatArray(this.getAsArray());
2.148 +}
2.149 +
2.150 +CanvasMatrix4.prototype.makeIdentity = function()
2.151 +{
2.152 + this.m11 = 1;
2.153 + this.m12 = 0;
2.154 + this.m13 = 0;
2.155 + this.m14 = 0;
2.156 +
2.157 + this.m21 = 0;
2.158 + this.m22 = 1;
2.159 + this.m23 = 0;
2.160 + this.m24 = 0;
2.161 +
2.162 + this.m31 = 0;
2.163 + this.m32 = 0;
2.164 + this.m33 = 1;
2.165 + this.m34 = 0;
2.166 +
2.167 + this.m41 = 0;
2.168 + this.m42 = 0;
2.169 + this.m43 = 0;
2.170 + this.m44 = 1;
2.171 +}
2.172 +
2.173 +CanvasMatrix4.prototype.transpose = function()
2.174 +{
2.175 + var tmp = this.m12;
2.176 + this.m12 = this.m21;
2.177 + this.m21 = tmp;
2.178 +
2.179 + tmp = this.m13;
2.180 + this.m13 = this.m31;
2.181 + this.m31 = tmp;
2.182 +
2.183 + tmp = this.m14;
2.184 + this.m14 = this.m41;
2.185 + this.m41 = tmp;
2.186 +
2.187 + tmp = this.m23;
2.188 + this.m23 = this.m32;
2.189 + this.m32 = tmp;
2.190 +
2.191 + tmp = this.m24;
2.192 + this.m24 = this.m42;
2.193 + this.m42 = tmp;
2.194 +
2.195 + tmp = this.m34;
2.196 + this.m34 = this.m43;
2.197 + this.m43 = tmp;
2.198 +}
2.199 +
2.200 +CanvasMatrix4.prototype.invert = function()
2.201 +{
2.202 + // Calculate the 4x4 determinant
2.203 + // If the determinant is zero,
2.204 + // then the inverse matrix is not unique.
2.205 + var det = this._determinant4x4();
2.206 +
2.207 + if (Math.abs(det) < 1e-8)
2.208 + return null;
2.209 +
2.210 + this._makeAdjoint();
2.211 +
2.212 + // Scale the adjoint matrix to get the inverse
2.213 + this.m11 /= det;
2.214 + this.m12 /= det;
2.215 + this.m13 /= det;
2.216 + this.m14 /= det;
2.217 +
2.218 + this.m21 /= det;
2.219 + this.m22 /= det;
2.220 + this.m23 /= det;
2.221 + this.m24 /= det;
2.222 +
2.223 + this.m31 /= det;
2.224 + this.m32 /= det;
2.225 + this.m33 /= det;
2.226 + this.m34 /= det;
2.227 +
2.228 + this.m41 /= det;
2.229 + this.m42 /= det;
2.230 + this.m43 /= det;
2.231 + this.m44 /= det;
2.232 +}
2.233 +
2.234 +CanvasMatrix4.prototype.translate = function(x,y,z)
2.235 +{
2.236 + if (x == undefined)
2.237 + x = 0;
2.238 + if (y == undefined)
2.239 + y = 0;
2.240 + if (z == undefined)
2.241 + z = 0;
2.242 +
2.243 + var matrix = new CanvasMatrix4();
2.244 + matrix.m41 = x;
2.245 + matrix.m42 = y;
2.246 + matrix.m43 = z;
2.247 +
2.248 + this.multRight(matrix);
2.249 +}
2.250 +
2.251 +CanvasMatrix4.prototype.scale = function(x,y,z)
2.252 +{
2.253 + if (x == undefined)
2.254 + x = 1;
2.255 + if (z == undefined) {
2.256 + if (y == undefined) {
2.257 + y = x;
2.258 + z = x;
2.259 + }
2.260 + else
2.261 + z = 1;
2.262 + }
2.263 + else if (y == undefined)
2.264 + y = x;
2.265 +
2.266 + var matrix = new CanvasMatrix4();
2.267 + matrix.m11 = x;
2.268 + matrix.m22 = y;
2.269 + matrix.m33 = z;
2.270 +
2.271 + this.multRight(matrix);
2.272 +}
2.273 +
2.274 +CanvasMatrix4.prototype.rotate = function(angle,x,y,z)
2.275 +{
2.276 + // angles are in degrees. Switch to radians
2.277 + angle = angle / 180 * Math.PI;
2.278 +
2.279 + angle /= 2;
2.280 + var sinA = Math.sin(angle);
2.281 + var cosA = Math.cos(angle);
2.282 + var sinA2 = sinA * sinA;
2.283 +
2.284 + // normalize
2.285 + var length = Math.sqrt(x * x + y * y + z * z);
2.286 + if (length == 0) {
2.287 + // bad vector, just use something reasonable
2.288 + x = 0;
2.289 + y = 0;
2.290 + z = 1;
2.291 + } else if (length != 1) {
2.292 + x /= length;
2.293 + y /= length;
2.294 + z /= length;
2.295 + }
2.296 +
2.297 + var mat = new CanvasMatrix4();
2.298 +
2.299 + // optimize case where axis is along major axis
2.300 + if (x == 1 && y == 0 && z == 0) {
2.301 + mat.m11 = 1;
2.302 + mat.m12 = 0;
2.303 + mat.m13 = 0;
2.304 + mat.m21 = 0;
2.305 + mat.m22 = 1 - 2 * sinA2;
2.306 + mat.m23 = 2 * sinA * cosA;
2.307 + mat.m31 = 0;
2.308 + mat.m32 = -2 * sinA * cosA;
2.309 + mat.m33 = 1 - 2 * sinA2;
2.310 + mat.m14 = mat.m24 = mat.m34 = 0;
2.311 + mat.m41 = mat.m42 = mat.m43 = 0;
2.312 + mat.m44 = 1;
2.313 + } else if (x == 0 && y == 1 && z == 0) {
2.314 + mat.m11 = 1 - 2 * sinA2;
2.315 + mat.m12 = 0;
2.316 + mat.m13 = -2 * sinA * cosA;
2.317 + mat.m21 = 0;
2.318 + mat.m22 = 1;
2.319 + mat.m23 = 0;
2.320 + mat.m31 = 2 * sinA * cosA;
2.321 + mat.m32 = 0;
2.322 + mat.m33 = 1 - 2 * sinA2;
2.323 + mat.m14 = mat.m24 = mat.m34 = 0;
2.324 + mat.m41 = mat.m42 = mat.m43 = 0;
2.325 + mat.m44 = 1;
2.326 + } else if (x == 0 && y == 0 && z == 1) {
2.327 + mat.m11 = 1 - 2 * sinA2;
2.328 + mat.m12 = 2 * sinA * cosA;
2.329 + mat.m13 = 0;
2.330 + mat.m21 = -2 * sinA * cosA;
2.331 + mat.m22 = 1 - 2 * sinA2;
2.332 + mat.m23 = 0;
2.333 + mat.m31 = 0;
2.334 + mat.m32 = 0;
2.335 + mat.m33 = 1;
2.336 + mat.m14 = mat.m24 = mat.m34 = 0;
2.337 + mat.m41 = mat.m42 = mat.m43 = 0;
2.338 + mat.m44 = 1;
2.339 + } else {
2.340 + var x2 = x*x;
2.341 + var y2 = y*y;
2.342 + var z2 = z*z;
2.343 +
2.344 + mat.m11 = 1 - 2 * (y2 + z2) * sinA2;
2.345 + mat.m12 = 2 * (x * y * sinA2 + z * sinA * cosA);
2.346 + mat.m13 = 2 * (x * z * sinA2 - y * sinA * cosA);
2.347 + mat.m21 = 2 * (y * x * sinA2 - z * sinA * cosA);
2.348 + mat.m22 = 1 - 2 * (z2 + x2) * sinA2;
2.349 + mat.m23 = 2 * (y * z * sinA2 + x * sinA * cosA);
2.350 + mat.m31 = 2 * (z * x * sinA2 + y * sinA * cosA);
2.351 + mat.m32 = 2 * (z * y * sinA2 - x * sinA * cosA);
2.352 + mat.m33 = 1 - 2 * (x2 + y2) * sinA2;
2.353 + mat.m14 = mat.m24 = mat.m34 = 0;
2.354 + mat.m41 = mat.m42 = mat.m43 = 0;
2.355 + mat.m44 = 1;
2.356 + }
2.357 + this.multRight(mat);
2.358 +}
2.359 +
2.360 +CanvasMatrix4.prototype.multRight = function(mat)
2.361 +{
2.362 + var m11 = (this.m11 * mat.m11 + this.m12 * mat.m21
2.363 + + this.m13 * mat.m31 + this.m14 * mat.m41);
2.364 + var m12 = (this.m11 * mat.m12 + this.m12 * mat.m22
2.365 + + this.m13 * mat.m32 + this.m14 * mat.m42);
2.366 + var m13 = (this.m11 * mat.m13 + this.m12 * mat.m23
2.367 + + this.m13 * mat.m33 + this.m14 * mat.m43);
2.368 + var m14 = (this.m11 * mat.m14 + this.m12 * mat.m24
2.369 + + this.m13 * mat.m34 + this.m14 * mat.m44);
2.370 +
2.371 + var m21 = (this.m21 * mat.m11 + this.m22 * mat.m21
2.372 + + this.m23 * mat.m31 + this.m24 * mat.m41);
2.373 + var m22 = (this.m21 * mat.m12 + this.m22 * mat.m22
2.374 + + this.m23 * mat.m32 + this.m24 * mat.m42);
2.375 + var m23 = (this.m21 * mat.m13 + this.m22 * mat.m23
2.376 + + this.m23 * mat.m33 + this.m24 * mat.m43);
2.377 + var m24 = (this.m21 * mat.m14 + this.m22 * mat.m24
2.378 + + this.m23 * mat.m34 + this.m24 * mat.m44);
2.379 +
2.380 + var m31 = (this.m31 * mat.m11 + this.m32 * mat.m21
2.381 + + this.m33 * mat.m31 + this.m34 * mat.m41);
2.382 + var m32 = (this.m31 * mat.m12 + this.m32 * mat.m22
2.383 + + this.m33 * mat.m32 + this.m34 * mat.m42);
2.384 + var m33 = (this.m31 * mat.m13 + this.m32 * mat.m23
2.385 + + this.m33 * mat.m33 + this.m34 * mat.m43);
2.386 + var m34 = (this.m31 * mat.m14 + this.m32 * mat.m24
2.387 + + this.m33 * mat.m34 + this.m34 * mat.m44);
2.388 +
2.389 + var m41 = (this.m41 * mat.m11 + this.m42 * mat.m21
2.390 + + this.m43 * mat.m31 + this.m44 * mat.m41);
2.391 + var m42 = (this.m41 * mat.m12 + this.m42 * mat.m22
2.392 + + this.m43 * mat.m32 + this.m44 * mat.m42);
2.393 + var m43 = (this.m41 * mat.m13 + this.m42 * mat.m23
2.394 + + this.m43 * mat.m33 + this.m44 * mat.m43);
2.395 + var m44 = (this.m41 * mat.m14 + this.m42 * mat.m24
2.396 + + this.m43 * mat.m34 + this.m44 * mat.m44);
2.397 +
2.398 + this.m11 = m11;
2.399 + this.m12 = m12;
2.400 + this.m13 = m13;
2.401 + this.m14 = m14;
2.402 +
2.403 + this.m21 = m21;
2.404 + this.m22 = m22;
2.405 + this.m23 = m23;
2.406 + this.m24 = m24;
2.407 +
2.408 + this.m31 = m31;
2.409 + this.m32 = m32;
2.410 + this.m33 = m33;
2.411 + this.m34 = m34;
2.412 +
2.413 + this.m41 = m41;
2.414 + this.m42 = m42;
2.415 + this.m43 = m43;
2.416 + this.m44 = m44;
2.417 +}
2.418 +
2.419 +CanvasMatrix4.prototype.multLeft = function(mat)
2.420 +{
2.421 + var m11 = (mat.m11 * this.m11 + mat.m12 * this.m21
2.422 + + mat.m13 * this.m31 + mat.m14 * this.m41);
2.423 + var m12 = (mat.m11 * this.m12 + mat.m12 * this.m22
2.424 + + mat.m13 * this.m32 + mat.m14 * this.m42);
2.425 + var m13 = (mat.m11 * this.m13 + mat.m12 * this.m23
2.426 + + mat.m13 * this.m33 + mat.m14 * this.m43);
2.427 + var m14 = (mat.m11 * this.m14 + mat.m12 * this.m24
2.428 + + mat.m13 * this.m34 + mat.m14 * this.m44);
2.429 +
2.430 + var m21 = (mat.m21 * this.m11 + mat.m22 * this.m21
2.431 + + mat.m23 * this.m31 + mat.m24 * this.m41);
2.432 + var m22 = (mat.m21 * this.m12 + mat.m22 * this.m22
2.433 + + mat.m23 * this.m32 + mat.m24 * this.m42);
2.434 + var m23 = (mat.m21 * this.m13 + mat.m22 * this.m23
2.435 + + mat.m23 * this.m33 + mat.m24 * this.m43);
2.436 + var m24 = (mat.m21 * this.m14 + mat.m22 * this.m24
2.437 + + mat.m23 * this.m34 + mat.m24 * this.m44);
2.438 +
2.439 + var m31 = (mat.m31 * this.m11 + mat.m32 * this.m21
2.440 + + mat.m33 * this.m31 + mat.m34 * this.m41);
2.441 + var m32 = (mat.m31 * this.m12 + mat.m32 * this.m22
2.442 + + mat.m33 * this.m32 + mat.m34 * this.m42);
2.443 + var m33 = (mat.m31 * this.m13 + mat.m32 * this.m23
2.444 + + mat.m33 * this.m33 + mat.m34 * this.m43);
2.445 + var m34 = (mat.m31 * this.m14 + mat.m32 * this.m24
2.446 + + mat.m33 * this.m34 + mat.m34 * this.m44);
2.447 +
2.448 + var m41 = (mat.m41 * this.m11 + mat.m42 * this.m21
2.449 + + mat.m43 * this.m31 + mat.m44 * this.m41);
2.450 + var m42 = (mat.m41 * this.m12 + mat.m42 * this.m22
2.451 + + mat.m43 * this.m32 + mat.m44 * this.m42);
2.452 + var m43 = (mat.m41 * this.m13 + mat.m42 * this.m23
2.453 + + mat.m43 * this.m33 + mat.m44 * this.m43);
2.454 + var m44 = (mat.m41 * this.m14 + mat.m42 * this.m24
2.455 + + mat.m43 * this.m34 + mat.m44 * this.m44);
2.456 +
2.457 + this.m11 = m11;
2.458 + this.m12 = m12;
2.459 + this.m13 = m13;
2.460 + this.m14 = m14;
2.461 +
2.462 + this.m21 = m21;
2.463 + this.m22 = m22;
2.464 + this.m23 = m23;
2.465 + this.m24 = m24;
2.466 +
2.467 + this.m31 = m31;
2.468 + this.m32 = m32;
2.469 + this.m33 = m33;
2.470 + this.m34 = m34;
2.471 +
2.472 + this.m41 = m41;
2.473 + this.m42 = m42;
2.474 + this.m43 = m43;
2.475 + this.m44 = m44;
2.476 +}
2.477 +
2.478 +CanvasMatrix4.prototype.ortho = function(left, right, bottom, top, near, far)
2.479 +{
2.480 + var tx = (left + right) / (left - right);
2.481 + var ty = (top + bottom) / (top - bottom);
2.482 + var tz = (far + near) / (far - near);
2.483 +
2.484 + var matrix = new CanvasMatrix4();
2.485 + matrix.m11 = 2 / (left - right);
2.486 + matrix.m12 = 0;
2.487 + matrix.m13 = 0;
2.488 + matrix.m14 = 0;
2.489 + matrix.m21 = 0;
2.490 + matrix.m22 = 2 / (top - bottom);
2.491 + matrix.m23 = 0;
2.492 + matrix.m24 = 0;
2.493 + matrix.m31 = 0;
2.494 + matrix.m32 = 0;
2.495 + matrix.m33 = -2 / (far - near);
2.496 + matrix.m34 = 0;
2.497 + matrix.m41 = tx;
2.498 + matrix.m42 = ty;
2.499 + matrix.m43 = tz;
2.500 + matrix.m44 = 1;
2.501 +
2.502 + this.multRight(matrix);
2.503 +}
2.504 +
2.505 +CanvasMatrix4.prototype.frustum = function(left, right, bottom, top, near, far)
2.506 +{
2.507 + var matrix = new CanvasMatrix4();
2.508 + var A = (right + left) / (right - left);
2.509 + var B = (top + bottom) / (top - bottom);
2.510 + var C = -(far + near) / (far - near);
2.511 + var D = -(2 * far * near) / (far - near);
2.512 +
2.513 + matrix.m11 = (2 * near) / (right - left);
2.514 + matrix.m12 = 0;
2.515 + matrix.m13 = 0;
2.516 + matrix.m14 = 0;
2.517 +
2.518 + matrix.m21 = 0;
2.519 + matrix.m22 = 2 * near / (top - bottom);
2.520 + matrix.m23 = 0;
2.521 + matrix.m24 = 0;
2.522 +
2.523 + matrix.m31 = A;
2.524 + matrix.m32 = B;
2.525 + matrix.m33 = C;
2.526 + matrix.m34 = -1;
2.527 +
2.528 + matrix.m41 = 0;
2.529 + matrix.m42 = 0;
2.530 + matrix.m43 = D;
2.531 + matrix.m44 = 0;
2.532 +
2.533 + this.multRight(matrix);
2.534 +}
2.535 +
2.536 +CanvasMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar)
2.537 +{
2.538 + var top = Math.tan(fovy * Math.PI / 360) * zNear;
2.539 + var bottom = -top;
2.540 + var left = aspect * bottom;
2.541 + var right = aspect * top;
2.542 + this.frustum(left, right, bottom, top, zNear, zFar);
2.543 +}
2.544 +
2.545 +CanvasMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
2.546 +{
2.547 + var matrix = new CanvasMatrix4();
2.548 +
2.549 + // Make rotation matrix
2.550 +
2.551 + // Z vector
2.552 + var zx = eyex - centerx;
2.553 + var zy = eyey - centery;
2.554 + var zz = eyez - centerz;
2.555 + var mag = Math.sqrt(zx * zx + zy * zy + zz * zz);
2.556 + if (mag) {
2.557 + zx /= mag;
2.558 + zy /= mag;
2.559 + zz /= mag;
2.560 + }
2.561 +
2.562 + // Y vector
2.563 + var yx = upx;
2.564 + var yy = upy;
2.565 + var yz = upz;
2.566 +
2.567 + // X vector = Y cross Z
2.568 + xx = yy * zz - yz * zy;
2.569 + xy = -yx * zz + yz * zx;
2.570 + xz = yx * zy - yy * zx;
2.571 +
2.572 + // Recompute Y = Z cross X
2.573 + yx = zy * xz - zz * xy;
2.574 + yy = -zx * xz + zz * xx;
2.575 + yx = zx * xy - zy * xx;
2.576 +
2.577 + // cross product gives area of parallelogram, which is < 1.0 for
2.578 + // non-perpendicular unit-length vectors; so normalize x, y here
2.579 +
2.580 + mag = Math.sqrt(xx * xx + xy * xy + xz * xz);
2.581 + if (mag) {
2.582 + xx /= mag;
2.583 + xy /= mag;
2.584 + xz /= mag;
2.585 + }
2.586 +
2.587 + mag = Math.sqrt(yx * yx + yy * yy + yz * yz);
2.588 + if (mag) {
2.589 + yx /= mag;
2.590 + yy /= mag;
2.591 + yz /= mag;
2.592 + }
2.593 +
2.594 + matrix.m11 = xx;
2.595 + matrix.m12 = xy;
2.596 + matrix.m13 = xz;
2.597 + matrix.m14 = 0;
2.598 +
2.599 + matrix.m21 = yx;
2.600 + matrix.m22 = yy;
2.601 + matrix.m23 = yz;
2.602 + matrix.m24 = 0;
2.603 +
2.604 + matrix.m31 = zx;
2.605 + matrix.m32 = zy;
2.606 + matrix.m33 = zz;
2.607 + matrix.m34 = 0;
2.608 +
2.609 + matrix.m41 = 0;
2.610 + matrix.m42 = 0;
2.611 + matrix.m43 = 0;
2.612 + matrix.m44 = 1;
2.613 + matrix.translate(-eyex, -eyey, -eyez);
2.614 +
2.615 + this.multRight(matrix);
2.616 +}
2.617 +
2.618 +// Support functions
2.619 +CanvasMatrix4.prototype._determinant2x2 = function(a, b, c, d)
2.620 +{
2.621 + return a * d - b * c;
2.622 +}
2.623 +
2.624 +CanvasMatrix4.prototype._determinant3x3 = function(a1, a2, a3, b1, b2, b3, c1, c2, c3)
2.625 +{
2.626 + return a1 * this._determinant2x2(b2, b3, c2, c3)
2.627 + - b1 * this._determinant2x2(a2, a3, c2, c3)
2.628 + + c1 * this._determinant2x2(a2, a3, b2, b3);
2.629 +}
2.630 +
2.631 +CanvasMatrix4.prototype._determinant4x4 = function()
2.632 +{
2.633 + var a1 = this.m11;
2.634 + var b1 = this.m12;
2.635 + var c1 = this.m13;
2.636 + var d1 = this.m14;
2.637 +
2.638 + var a2 = this.m21;
2.639 + var b2 = this.m22;
2.640 + var c2 = this.m23;
2.641 + var d2 = this.m24;
2.642 +
2.643 + var a3 = this.m31;
2.644 + var b3 = this.m32;
2.645 + var c3 = this.m33;
2.646 + var d3 = this.m34;
2.647 +
2.648 + var a4 = this.m41;
2.649 + var b4 = this.m42;
2.650 + var c4 = this.m43;
2.651 + var d4 = this.m44;
2.652 +
2.653 + return a1 * this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
2.654 + - b1 * this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
2.655 + + c1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
2.656 + - d1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
2.657 +}
2.658 +
2.659 +CanvasMatrix4.prototype._makeAdjoint = function()
2.660 +{
2.661 + var a1 = this.m11;
2.662 + var b1 = this.m12;
2.663 + var c1 = this.m13;
2.664 + var d1 = this.m14;
2.665 +
2.666 + var a2 = this.m21;
2.667 + var b2 = this.m22;
2.668 + var c2 = this.m23;
2.669 + var d2 = this.m24;
2.670 +
2.671 + var a3 = this.m31;
2.672 + var b3 = this.m32;
2.673 + var c3 = this.m33;
2.674 + var d3 = this.m34;
2.675 +
2.676 + var a4 = this.m41;
2.677 + var b4 = this.m42;
2.678 + var c4 = this.m43;
2.679 + var d4 = this.m44;
2.680 +
2.681 + // Row column labeling reversed since we transpose rows & columns
2.682 + this.m11 = this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
2.683 + this.m21 = - this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
2.684 + this.m31 = this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
2.685 + this.m41 = - this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
2.686 +
2.687 + this.m12 = - this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
2.688 + this.m22 = this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
2.689 + this.m32 = - this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
2.690 + this.m42 = this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
2.691 +
2.692 + this.m13 = this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
2.693 + this.m23 = - this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
2.694 + this.m33 = this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
2.695 + this.m43 = - this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
2.696 +
2.697 + this.m14 = - this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
2.698 + this.m24 = this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
2.699 + this.m34 = - this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
2.700 + this.m44 = this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
2.701 +}
2.702 \ No newline at end of file
3.1 --- a/scripts/glMatrix.js Fri Apr 01 01:45:39 2011 +0200
3.2 +++ b/scripts/glMatrix.js Fri Apr 01 01:51:08 2011 +0200
3.3 @@ -0,0 +1,32 @@
3.4 +// glMatrix v0.9.5
3.5 +glMatrixArrayType=typeof Float32Array!="undefined"?Float32Array:typeof WebGLFloatArray!="undefined"?WebGLFloatArray:Array;var vec3={};vec3.create=function(a){var b=new glMatrixArrayType(3);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2]}return b};vec3.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];return b};vec3.add=function(a,b,c){if(!c||a==c){a[0]+=b[0];a[1]+=b[1];a[2]+=b[2];return a}c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];return c};
3.6 +vec3.subtract=function(a,b,c){if(!c||a==c){a[0]-=b[0];a[1]-=b[1];a[2]-=b[2];return a}c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];return c};vec3.negate=function(a,b){b||(b=a);b[0]=-a[0];b[1]=-a[1];b[2]=-a[2];return b};vec3.scale=function(a,b,c){if(!c||a==c){a[0]*=b;a[1]*=b;a[2]*=b;return a}c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;return c};
3.7 +vec3.normalize=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=Math.sqrt(c*c+d*d+e*e);if(g){if(g==1){b[0]=c;b[1]=d;b[2]=e;return b}}else{b[0]=0;b[1]=0;b[2]=0;return b}g=1/g;b[0]=c*g;b[1]=d*g;b[2]=e*g;return b};vec3.cross=function(a,b,c){c||(c=a);var d=a[0],e=a[1];a=a[2];var g=b[0],f=b[1];b=b[2];c[0]=e*b-a*f;c[1]=a*g-d*b;c[2]=d*f-e*g;return c};vec3.length=function(a){var b=a[0],c=a[1];a=a[2];return Math.sqrt(b*b+c*c+a*a)};vec3.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]};
3.8 +vec3.direction=function(a,b,c){c||(c=a);var d=a[0]-b[0],e=a[1]-b[1];a=a[2]-b[2];b=Math.sqrt(d*d+e*e+a*a);if(!b){c[0]=0;c[1]=0;c[2]=0;return c}b=1/b;c[0]=d*b;c[1]=e*b;c[2]=a*b;return c};vec3.lerp=function(a,b,c,d){d||(d=a);d[0]=a[0]+c*(b[0]-a[0]);d[1]=a[1]+c*(b[1]-a[1]);d[2]=a[2]+c*(b[2]-a[2]);return d};vec3.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+"]"};var mat3={};
3.9 +mat3.create=function(a){var b=new glMatrixArrayType(9);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9]}return b};mat3.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];return b};mat3.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=1;a[5]=0;a[6]=0;a[7]=0;a[8]=1;return a};
3.10 +mat3.transpose=function(a,b){if(!b||a==b){var c=a[1],d=a[2],e=a[5];a[1]=a[3];a[2]=a[6];a[3]=c;a[5]=a[7];a[6]=d;a[7]=e;return a}b[0]=a[0];b[1]=a[3];b[2]=a[6];b[3]=a[1];b[4]=a[4];b[5]=a[7];b[6]=a[2];b[7]=a[5];b[8]=a[8];return b};mat3.toMat4=function(a,b){b||(b=mat4.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=0;b[4]=a[3];b[5]=a[4];b[6]=a[5];b[7]=0;b[8]=a[6];b[9]=a[7];b[10]=a[8];b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b};
3.11 +mat3.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+"]"};var mat4={};mat4.create=function(a){var b=new glMatrixArrayType(16);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15]}return b};
3.12 +mat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return b};mat4.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=1;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=1;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1;return a};
3.13 +mat4.transpose=function(a,b){if(!b||a==b){var c=a[1],d=a[2],e=a[3],g=a[6],f=a[7],h=a[11];a[1]=a[4];a[2]=a[8];a[3]=a[12];a[4]=c;a[6]=a[9];a[7]=a[13];a[8]=d;a[9]=g;a[11]=a[14];a[12]=e;a[13]=f;a[14]=h;return a}b[0]=a[0];b[1]=a[4];b[2]=a[8];b[3]=a[12];b[4]=a[1];b[5]=a[5];b[6]=a[9];b[7]=a[13];b[8]=a[2];b[9]=a[6];b[10]=a[10];b[11]=a[14];b[12]=a[3];b[13]=a[7];b[14]=a[11];b[15]=a[15];return b};
3.14 +mat4.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],g=a[4],f=a[5],h=a[6],i=a[7],j=a[8],k=a[9],l=a[10],o=a[11],m=a[12],n=a[13],p=a[14];a=a[15];return m*k*h*e-j*n*h*e-m*f*l*e+g*n*l*e+j*f*p*e-g*k*p*e-m*k*d*i+j*n*d*i+m*c*l*i-b*n*l*i-j*c*p*i+b*k*p*i+m*f*d*o-g*n*d*o-m*c*h*o+b*n*h*o+g*c*p*o-b*f*p*o-j*f*d*a+g*k*d*a+j*c*h*a-b*k*h*a-g*c*l*a+b*f*l*a};
3.15 +mat4.inverse=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=a[3],f=a[4],h=a[5],i=a[6],j=a[7],k=a[8],l=a[9],o=a[10],m=a[11],n=a[12],p=a[13],r=a[14],s=a[15],A=c*h-d*f,B=c*i-e*f,t=c*j-g*f,u=d*i-e*h,v=d*j-g*h,w=e*j-g*i,x=k*p-l*n,y=k*r-o*n,z=k*s-m*n,C=l*r-o*p,D=l*s-m*p,E=o*s-m*r,q=1/(A*E-B*D+t*C+u*z-v*y+w*x);b[0]=(h*E-i*D+j*C)*q;b[1]=(-d*E+e*D-g*C)*q;b[2]=(p*w-r*v+s*u)*q;b[3]=(-l*w+o*v-m*u)*q;b[4]=(-f*E+i*z-j*y)*q;b[5]=(c*E-e*z+g*y)*q;b[6]=(-n*w+r*t-s*B)*q;b[7]=(k*w-o*t+m*B)*q;b[8]=(f*D-h*z+j*x)*q;
3.16 +b[9]=(-c*D+d*z-g*x)*q;b[10]=(n*v-p*t+s*A)*q;b[11]=(-k*v+l*t-m*A)*q;b[12]=(-f*C+h*y-i*x)*q;b[13]=(c*C-d*y+e*x)*q;b[14]=(-n*u+p*B-r*A)*q;b[15]=(k*u-l*B+o*A)*q;return b};mat4.toRotationMat=function(a,b){b||(b=mat4.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b};
3.17 +mat4.toMat3=function(a,b){b||(b=mat3.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[4];b[4]=a[5];b[5]=a[6];b[6]=a[8];b[7]=a[9];b[8]=a[10];return b};mat4.toInverseMat3=function(a,b){var c=a[0],d=a[1],e=a[2],g=a[4],f=a[5],h=a[6],i=a[8],j=a[9],k=a[10],l=k*f-h*j,o=-k*g+h*i,m=j*g-f*i,n=c*l+d*o+e*m;if(!n)return null;n=1/n;b||(b=mat3.create());b[0]=l*n;b[1]=(-k*d+e*j)*n;b[2]=(h*d-e*f)*n;b[3]=o*n;b[4]=(k*c-e*i)*n;b[5]=(-h*c+e*g)*n;b[6]=m*n;b[7]=(-j*c+d*i)*n;b[8]=(f*c-d*g)*n;return b};
3.18 +mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],g=a[2],f=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],o=a[9],m=a[10],n=a[11],p=a[12],r=a[13],s=a[14];a=a[15];var A=b[0],B=b[1],t=b[2],u=b[3],v=b[4],w=b[5],x=b[6],y=b[7],z=b[8],C=b[9],D=b[10],E=b[11],q=b[12],F=b[13],G=b[14];b=b[15];c[0]=A*d+B*h+t*l+u*p;c[1]=A*e+B*i+t*o+u*r;c[2]=A*g+B*j+t*m+u*s;c[3]=A*f+B*k+t*n+u*a;c[4]=v*d+w*h+x*l+y*p;c[5]=v*e+w*i+x*o+y*r;c[6]=v*g+w*j+x*m+y*s;c[7]=v*f+w*k+x*n+y*a;c[8]=z*d+C*h+D*l+E*p;c[9]=z*e+C*i+D*o+E*r;c[10]=z*
3.19 +g+C*j+D*m+E*s;c[11]=z*f+C*k+D*n+E*a;c[12]=q*d+F*h+G*l+b*p;c[13]=q*e+F*i+G*o+b*r;c[14]=q*g+F*j+G*m+b*s;c[15]=q*f+F*k+G*n+b*a;return c};mat4.multiplyVec3=function(a,b,c){c||(c=b);var d=b[0],e=b[1];b=b[2];c[0]=a[0]*d+a[4]*e+a[8]*b+a[12];c[1]=a[1]*d+a[5]*e+a[9]*b+a[13];c[2]=a[2]*d+a[6]*e+a[10]*b+a[14];return c};
3.20 +mat4.multiplyVec4=function(a,b,c){c||(c=b);var d=b[0],e=b[1],g=b[2];b=b[3];c[0]=a[0]*d+a[4]*e+a[8]*g+a[12]*b;c[1]=a[1]*d+a[5]*e+a[9]*g+a[13]*b;c[2]=a[2]*d+a[6]*e+a[10]*g+a[14]*b;c[3]=a[3]*d+a[7]*e+a[11]*g+a[15]*b;return c};
3.21 +mat4.translate=function(a,b,c){var d=b[0],e=b[1];b=b[2];if(!c||a==c){a[12]=a[0]*d+a[4]*e+a[8]*b+a[12];a[13]=a[1]*d+a[5]*e+a[9]*b+a[13];a[14]=a[2]*d+a[6]*e+a[10]*b+a[14];a[15]=a[3]*d+a[7]*e+a[11]*b+a[15];return a}var g=a[0],f=a[1],h=a[2],i=a[3],j=a[4],k=a[5],l=a[6],o=a[7],m=a[8],n=a[9],p=a[10],r=a[11];c[0]=g;c[1]=f;c[2]=h;c[3]=i;c[4]=j;c[5]=k;c[6]=l;c[7]=o;c[8]=m;c[9]=n;c[10]=p;c[11]=r;c[12]=g*d+j*e+m*b+a[12];c[13]=f*d+k*e+n*b+a[13];c[14]=h*d+l*e+p*b+a[14];c[15]=i*d+o*e+r*b+a[15];return c};
3.22 +mat4.scale=function(a,b,c){var d=b[0],e=b[1];b=b[2];if(!c||a==c){a[0]*=d;a[1]*=d;a[2]*=d;a[3]*=d;a[4]*=e;a[5]*=e;a[6]*=e;a[7]*=e;a[8]*=b;a[9]*=b;a[10]*=b;a[11]*=b;return a}c[0]=a[0]*d;c[1]=a[1]*d;c[2]=a[2]*d;c[3]=a[3]*d;c[4]=a[4]*e;c[5]=a[5]*e;c[6]=a[6]*e;c[7]=a[7]*e;c[8]=a[8]*b;c[9]=a[9]*b;c[10]=a[10]*b;c[11]=a[11]*b;c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15];return c};
3.23 +mat4.rotate=function(a,b,c,d){var e=c[0],g=c[1];c=c[2];var f=Math.sqrt(e*e+g*g+c*c);if(!f)return null;if(f!=1){f=1/f;e*=f;g*=f;c*=f}var h=Math.sin(b),i=Math.cos(b),j=1-i;b=a[0];f=a[1];var k=a[2],l=a[3],o=a[4],m=a[5],n=a[6],p=a[7],r=a[8],s=a[9],A=a[10],B=a[11],t=e*e*j+i,u=g*e*j+c*h,v=c*e*j-g*h,w=e*g*j-c*h,x=g*g*j+i,y=c*g*j+e*h,z=e*c*j+g*h;e=g*c*j-e*h;g=c*c*j+i;if(d){if(a!=d){d[12]=a[12];d[13]=a[13];d[14]=a[14];d[15]=a[15]}}else d=a;d[0]=b*t+o*u+r*v;d[1]=f*t+m*u+s*v;d[2]=k*t+n*u+A*v;d[3]=l*t+p*u+B*
3.24 +v;d[4]=b*w+o*x+r*y;d[5]=f*w+m*x+s*y;d[6]=k*w+n*x+A*y;d[7]=l*w+p*x+B*y;d[8]=b*z+o*e+r*g;d[9]=f*z+m*e+s*g;d[10]=k*z+n*e+A*g;d[11]=l*z+p*e+B*g;return d};mat4.rotateX=function(a,b,c){var d=Math.sin(b);b=Math.cos(b);var e=a[4],g=a[5],f=a[6],h=a[7],i=a[8],j=a[9],k=a[10],l=a[11];if(c){if(a!=c){c[0]=a[0];c[1]=a[1];c[2]=a[2];c[3]=a[3];c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15]}}else c=a;c[4]=e*b+i*d;c[5]=g*b+j*d;c[6]=f*b+k*d;c[7]=h*b+l*d;c[8]=e*-d+i*b;c[9]=g*-d+j*b;c[10]=f*-d+k*b;c[11]=h*-d+l*b;return c};
3.25 +mat4.rotateY=function(a,b,c){var d=Math.sin(b);b=Math.cos(b);var e=a[0],g=a[1],f=a[2],h=a[3],i=a[8],j=a[9],k=a[10],l=a[11];if(c){if(a!=c){c[4]=a[4];c[5]=a[5];c[6]=a[6];c[7]=a[7];c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15]}}else c=a;c[0]=e*b+i*-d;c[1]=g*b+j*-d;c[2]=f*b+k*-d;c[3]=h*b+l*-d;c[8]=e*d+i*b;c[9]=g*d+j*b;c[10]=f*d+k*b;c[11]=h*d+l*b;return c};
3.26 +mat4.rotateZ=function(a,b,c){var d=Math.sin(b);b=Math.cos(b);var e=a[0],g=a[1],f=a[2],h=a[3],i=a[4],j=a[5],k=a[6],l=a[7];if(c){if(a!=c){c[8]=a[8];c[9]=a[9];c[10]=a[10];c[11]=a[11];c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15]}}else c=a;c[0]=e*b+i*d;c[1]=g*b+j*d;c[2]=f*b+k*d;c[3]=h*b+l*d;c[4]=e*-d+i*b;c[5]=g*-d+j*b;c[6]=f*-d+k*b;c[7]=h*-d+l*b;return c};
3.27 +mat4.frustum=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=e*2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e*2/i;f[6]=0;f[7]=0;f[8]=(b+a)/h;f[9]=(d+c)/i;f[10]=-(g+e)/j;f[11]=-1;f[12]=0;f[13]=0;f[14]=-(g*e*2)/j;f[15]=0;return f};mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b=a*b;return mat4.frustum(-b,b,-a,a,c,d,e)};
3.28 +mat4.ortho=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=2/i;f[6]=0;f[7]=0;f[8]=0;f[9]=0;f[10]=-2/j;f[11]=0;f[12]=-(a+b)/h;f[13]=-(d+c)/i;f[14]=-(g+e)/j;f[15]=1;return f};
3.29 +mat4.lookAt=function(a,b,c,d){d||(d=mat4.create());var e=a[0],g=a[1];a=a[2];var f=c[0],h=c[1],i=c[2];c=b[1];var j=b[2];if(e==b[0]&&g==c&&a==j)return mat4.identity(d);var k,l,o,m;c=e-b[0];j=g-b[1];b=a-b[2];m=1/Math.sqrt(c*c+j*j+b*b);c*=m;j*=m;b*=m;k=h*b-i*j;i=i*c-f*b;f=f*j-h*c;if(m=Math.sqrt(k*k+i*i+f*f)){m=1/m;k*=m;i*=m;f*=m}else f=i=k=0;h=j*f-b*i;l=b*k-c*f;o=c*i-j*k;if(m=Math.sqrt(h*h+l*l+o*o)){m=1/m;h*=m;l*=m;o*=m}else o=l=h=0;d[0]=k;d[1]=h;d[2]=c;d[3]=0;d[4]=i;d[5]=l;d[6]=j;d[7]=0;d[8]=f;d[9]=
3.30 +o;d[10]=b;d[11]=0;d[12]=-(k*e+i*g+f*a);d[13]=-(h*e+l*g+o*a);d[14]=-(c*e+j*g+b*a);d[15]=1;return d};mat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+", "+a[9]+", "+a[10]+", "+a[11]+", "+a[12]+", "+a[13]+", "+a[14]+", "+a[15]+"]"};quat4={};quat4.create=function(a){var b=new glMatrixArrayType(4);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3]}return b};quat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];return b};
3.31 +quat4.calculateW=function(a,b){var c=a[0],d=a[1],e=a[2];if(!b||a==b){a[3]=-Math.sqrt(Math.abs(1-c*c-d*d-e*e));return a}b[0]=c;b[1]=d;b[2]=e;b[3]=-Math.sqrt(Math.abs(1-c*c-d*d-e*e));return b};quat4.inverse=function(a,b){if(!b||a==b){a[0]*=1;a[1]*=1;a[2]*=1;return a}b[0]=-a[0];b[1]=-a[1];b[2]=-a[2];b[3]=a[3];return b};quat4.length=function(a){var b=a[0],c=a[1],d=a[2];a=a[3];return Math.sqrt(b*b+c*c+d*d+a*a)};
3.32 +quat4.normalize=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=a[3],f=Math.sqrt(c*c+d*d+e*e+g*g);if(f==0){b[0]=0;b[1]=0;b[2]=0;b[3]=0;return b}f=1/f;b[0]=c*f;b[1]=d*f;b[2]=e*f;b[3]=g*f;return b};quat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],g=a[2];a=a[3];var f=b[0],h=b[1],i=b[2];b=b[3];c[0]=d*b+a*f+e*i-g*h;c[1]=e*b+a*h+g*f-d*i;c[2]=g*b+a*i+d*h-e*f;c[3]=a*b-d*f-e*h-g*i;return c};
3.33 +quat4.multiplyVec3=function(a,b,c){c||(c=b);var d=b[0],e=b[1],g=b[2];b=a[0];var f=a[1],h=a[2];a=a[3];var i=a*d+f*g-h*e,j=a*e+h*d-b*g,k=a*g+b*e-f*d;d=-b*d-f*e-h*g;c[0]=i*a+d*-b+j*-h-k*-f;c[1]=j*a+d*-f+k*-b-i*-h;c[2]=k*a+d*-h+i*-f-j*-b;return c};quat4.toMat3=function(a,b){b||(b=mat3.create());var c=a[0],d=a[1],e=a[2],g=a[3],f=c+c,h=d+d,i=e+e,j=c*f,k=c*h;c=c*i;var l=d*h;d=d*i;e=e*i;f=g*f;h=g*h;g=g*i;b[0]=1-(l+e);b[1]=k-g;b[2]=c+h;b[3]=k+g;b[4]=1-(j+e);b[5]=d-f;b[6]=c-h;b[7]=d+f;b[8]=1-(j+l);return b};
3.34 +quat4.toMat4=function(a,b){b||(b=mat4.create());var c=a[0],d=a[1],e=a[2],g=a[3],f=c+c,h=d+d,i=e+e,j=c*f,k=c*h;c=c*i;var l=d*h;d=d*i;e=e*i;f=g*f;h=g*h;g=g*i;b[0]=1-(l+e);b[1]=k-g;b[2]=c+h;b[3]=0;b[4]=k+g;b[5]=1-(j+e);b[6]=d-f;b[7]=0;b[8]=c-h;b[9]=d+f;b[10]=1-(j+l);b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b};quat4.slerp=function(a,b,c,d){d||(d=a);var e=c;if(a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]<0)e=-1*c;d[0]=1-c*a[0]+e*b[0];d[1]=1-c*a[1]+e*b[1];d[2]=1-c*a[2]+e*b[2];d[3]=1-c*a[3]+e*b[3];return d};
3.35 +quat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+"]"};
4.1 --- a/scripts/machine.js Fri Apr 01 01:45:39 2011 +0200
4.2 +++ b/scripts/machine.js Fri Apr 01 01:51:08 2011 +0200
4.3 @@ -0,0 +1,155 @@
4.4 +function Machine(canvas, context, scene)
4.5 +{
4.6 + this.canvas = canvas;
4.7 + this.context = context;
4.8 + this.scene = scene;
4.9 + this.gl = context.gl;
4.10 +}
4.11 +Machine.prototype.draw = function()
4.12 +{
4.13 + draw(this.context, this.scene);
4.14 +}
4.15 +
4.16 +var machine;
4.17 +
4.18 +function main()
4.19 +{
4.20 + var canvas = document.getElementById("machine");
4.21 + make_fullscreen(canvas);
4.22 + window.onresize = update;
4.23 + var context = new Context(canvas);
4.24 + var gl = context.gl;
4.25 + var object = new Box(1, context);
4.26 + gl.clearColor(0.0, 0.0, 0.0, 1.0);
4.27 + gl.enable(gl.DEPTH_TEST);
4.28 + //draw(context, object);
4.29 + machine = new Machine(canvas, context, object);
4.30 + machine.draw();
4.31 +}
4.32 +
4.33 +function update()
4.34 +{
4.35 + make_fullscreen(machine.canvas);
4.36 + //draw(machine.context, machine.scene);
4.37 + machine.draw();
4.38 +}
4.39 +
4.40 +function make_fullscreen(canvas)
4.41 +{
4.42 + canvas.width = window.innerWidth;
4.43 + canvas.height = window.innerHeight;
4.44 +}
4.45 +
4.46 +function Context(canvas)
4.47 +{
4.48 + try
4.49 + {
4.50 + this.gl = canvas.getContext("experimental-webgl");
4.51 + this.viewport = {'width': canvas.width,
4.52 + 'height': canvas.height};
4.53 + }
4.54 + catch(e)
4.55 + {
4.56 + alert(e);
4.57 + }
4.58 + if (!this.gl) alert("Failed: WebGL init.");
4.59 + this.mvMatrix = mat4.create();
4.60 + this.pMatrix = mat4.create();
4.61 + this.shader = new Shader(this);
4.62 +}
4.63 +Context.prototype.updateMatrixUniforms = function()
4.64 +{
4.65 + var gl = this.gl;
4.66 + var program = this.shader;
4.67 + var pMatrix = this.pMatrix;
4.68 + var mvMatrix = this.mvMatrix;
4.69 + gl.uniformMatrix4fv(program.pMatrixUniform, false, pMatrix);
4.70 + gl.uniformMatrix4fv(program.mvMatrixUniform, false, mvMatrix);
4.71 +}
4.72 +
4.73 +function Shader(context)
4.74 +{
4.75 + var gl = context.gl;
4.76 + var fragment = load_shader(gl, "fragment-shader");
4.77 + var vertex = load_shader(gl, "vertex-shader");
4.78 + this.program = gl.createProgram();
4.79 + gl.attachShader(this.program, vertex);
4.80 + gl.attachShader(this.program, fragment);
4.81 + gl.linkProgram(this.program);
4.82 +
4.83 + if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
4.84 + {
4.85 + alert("Failed: Shader init.");
4.86 + }
4.87 +
4.88 + gl.useProgram(this.program);
4.89 + this.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
4.90 + gl.enableVertexAttribArray(this.vertexPosition);
4.91 + this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
4.92 + this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");
4.93 +
4.94 + function load_shader(gl, id)
4.95 + {
4.96 + var script = document.getElementById(id);
4.97 + if (!script) return null;
4.98 +
4.99 + var str = "";
4.100 + var child = script.firstChild;
4.101 + while (child)
4.102 + {
4.103 + if (child.nodeType == 3) str += child.textContent;
4.104 + child = child.nextSibling;
4.105 + }
4.106 +
4.107 + var shader;
4.108 + var common = "x-shader/x-";
4.109 + if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER);
4.110 + else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER);
4.111 + else return null;
4.112 +
4.113 + gl.shaderSource(shader, str);
4.114 + gl.compileShader(shader);
4.115 +
4.116 + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
4.117 + {
4.118 + alert(gl.getShaderInfoLog(shader));
4.119 + return null;
4.120 + }
4.121 +
4.122 + return shader;
4.123 + }
4.124 +}
4.125 +
4.126 +
4.127 +function Box(size, context)
4.128 +{
4.129 + var gl = context.gl;
4.130 + this.size = size || 1;
4.131 + this.buffer = gl.createBuffer();
4.132 + gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
4.133 + var vertices = [1.0, 1.0, 0.0,
4.134 + -1.0, 1.0, 0.0,
4.135 + 1.0, -1.0, 0.0,
4.136 + -1.0, -1.0, 0.0];
4.137 + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
4.138 + this.itemSize = 3;
4.139 + this.numItems = 4;
4.140 +}
4.141 +
4.142 +function draw(context, scene)
4.143 +{
4.144 + var gl = context.gl;
4.145 + var viewport = context.viewport;
4.146 + var shader = context.shader;
4.147 + var mvMatrix = context.mvMatrix;
4.148 + var pMatrix = context.pMatrix;
4.149 + gl.viewport(0, 0, viewport.width, viewport.height);
4.150 + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
4.151 + mat4.perspective(45, viewport.width / viewport.height, 0.1, 100.0, pMatrix);
4.152 + mat4.identity(mvMatrix);
4.153 + mat4.translate(mvMatrix, [0.0, 0.0, -7.0]);
4.154 + gl.bindBuffer(gl.ARRAY_BUFFER, scene.buffer);
4.155 + gl.vertexAttribPointer(shader.vertexPosition, scene.itemSize, gl.FLOAT, false, 0, 0);
4.156 + context.updateMatrixUniforms();
4.157 + gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.numItems);
4.158 +}
4.159 \ No newline at end of file
5.1 --- a/scripts/utils3d.js Fri Apr 01 01:45:39 2011 +0200
5.2 +++ b/scripts/utils3d.js Fri Apr 01 01:51:08 2011 +0200
5.3 @@ -0,0 +1,530 @@
5.4 +//
5.5 +// initWebGL
5.6 +//
5.7 +// Initialize the Canvas element with the passed name as a WebGL object and return the
5.8 +// WebGLRenderingContext.
5.9 +//
5.10 +// Load shaders with the passed names and create a program with them. Return this program
5.11 +// in the 'program' property of the returned context.
5.12 +//
5.13 +// For each string in the passed attribs array, bind an attrib with that name at that index.
5.14 +// Once the attribs are bound, link the program and then use it.
5.15 +//
5.16 +// Set the clear color to the passed array (4 values) and set the clear depth to the passed value.
5.17 +// Enable depth testing and blending with a blend func of (SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
5.18 +//
5.19 +function initWebGL(canvasName, vshader, fshader, attribs, clearColor, clearDepth)
5.20 +{
5.21 + var canvas = document.getElementById(canvasName);
5.22 + var gl = canvas.getContext("webkit-3d");
5.23 +
5.24 + // create our shaders
5.25 + var vertexShader = loadShader(gl, vshader);
5.26 + var fragmentShader = loadShader(gl, fshader);
5.27 +
5.28 + if (!vertexShader || !fragmentShader)
5.29 + return null;
5.30 +
5.31 + // Create the program object
5.32 + gl.program = gl.createProgram();
5.33 +
5.34 + if (!gl.program)
5.35 + return null;
5.36 +
5.37 + // Attach our two shaders to the program
5.38 + gl.attachShader (gl.program, vertexShader);
5.39 + gl.attachShader (gl.program, fragmentShader);
5.40 +
5.41 + // Bind attributes
5.42 + for (var i in attribs)
5.43 + gl.bindAttribLocation (gl.program, i, attribs[i]);
5.44 +
5.45 + // Link the program
5.46 + gl.linkProgram(gl.program);
5.47 +
5.48 + // Check the link status
5.49 + var linked = gl.getProgrami(gl.program, gl.LINK_STATUS);
5.50 + if (!linked) {
5.51 + // something went wrong with the link
5.52 + var error = gl.getProgramInfoLog (gl.program);
5.53 + console.log("Error in program linking:"+error);
5.54 +
5.55 + gl.deleteProgram(gl.program);
5.56 + gl.deleteProgram(fragmentShader);
5.57 + gl.deleteProgram(vertexShader);
5.58 +
5.59 + return null;
5.60 + }
5.61 +
5.62 + gl.useProgram(gl.program);
5.63 +
5.64 + gl.clearColor (clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
5.65 + gl.clearDepth (clearDepth);
5.66 +
5.67 + gl.enable(gl.DEPTH_TEST);
5.68 + gl.enable(gl.BLEND);
5.69 + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
5.70 +
5.71 + return gl;
5.72 +}
5.73 +
5.74 +//
5.75 +// loadShader
5.76 +//
5.77 +// 'shaderId' is the id of a <script> element containing the shader source string.
5.78 +// Load this shader and return the WebGLShader object corresponding to it.
5.79 +//
5.80 +function loadShader(ctx, shaderId)
5.81 +{
5.82 + var shaderScript = document.getElementById(shaderId);
5.83 + if (!shaderScript) {
5.84 + console.log("*** Error: shader script '"+shaderId+"' not found");
5.85 + return null;
5.86 + }
5.87 +
5.88 + if (shaderScript.type == "x-shader/x-vertex")
5.89 + var shaderType = ctx.VERTEX_SHADER;
5.90 + else if (shaderScript.type == "x-shader/x-fragment")
5.91 + var shaderType = ctx.FRAGMENT_SHADER;
5.92 + else {
5.93 + console.log("*** Error: shader script '"+shaderId+"' of undefined type '"+shaderScript.type+"'");
5.94 + return null;
5.95 + }
5.96 +
5.97 + // Create the shader object
5.98 + var shader = ctx.createShader(shaderType);
5.99 + if (shader == null) {
5.100 + console.log("*** Error: unable to create shader '"+shaderId+"'");
5.101 + return null;
5.102 + }
5.103 +
5.104 + // Load the shader source
5.105 + ctx.shaderSource(shader, shaderScript.text);
5.106 +
5.107 + // Compile the shader
5.108 + ctx.compileShader(shader);
5.109 +
5.110 + // Check the compile status
5.111 + var compiled = ctx.getShaderi(shader, ctx.COMPILE_STATUS);
5.112 + if (!compiled) {
5.113 + // Something went wrong during compilation; get the error
5.114 + var error = ctx.getShaderInfoLog(shader);
5.115 + console.log("*** Error compiling shader '"+shaderId+"':"+error);
5.116 + ctx.deleteShader(shader);
5.117 + return null;
5.118 + }
5.119 +
5.120 + return shader;
5.121 +}
5.122 +
5.123 +//
5.124 +// makeBox
5.125 +//
5.126 +// Create a box with vertices, normals and texCoords. Create VBOs for each as well as the index array.
5.127 +// Return an object with the following properties:
5.128 +//
5.129 +// normalObject WebGLBuffer object for normals
5.130 +// texCoordObject WebGLBuffer object for texCoords
5.131 +// vertexObject WebGLBuffer object for vertices
5.132 +// indexObject WebGLBuffer object for indices
5.133 +// numIndices The number of indices in the indexObject
5.134 +//
5.135 +function makeBox(ctx)
5.136 +{
5.137 + // box
5.138 + // v6----- v5
5.139 + // /| /|
5.140 + // v1------v0|
5.141 + // | | | |
5.142 + // | |v7---|-|v4
5.143 + // |/ |/
5.144 + // v2------v3
5.145 + //
5.146 + // vertex coords array
5.147 + var vertices = new WebGLFloatArray(
5.148 + [ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0-v1-v2-v3 front
5.149 + 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0-v3-v4-v5 right
5.150 + 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0-v5-v6-v1 top
5.151 + -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1-v6-v7-v2 left
5.152 + -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7-v4-v3-v2 bottom
5.153 + 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 ] // v4-v7-v6-v5 back
5.154 + );
5.155 +
5.156 + // normal array
5.157 + var normals = new WebGLFloatArray(
5.158 + [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2-v3 front
5.159 + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right
5.160 + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0-v5-v6-v1 top
5.161 + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1-v6-v7-v2 left
5.162 + 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7-v4-v3-v2 bottom
5.163 + 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 ] // v4-v7-v6-v5 back
5.164 + );
5.165 +
5.166 +
5.167 + // texCoord array
5.168 + var texCoords = new WebGLFloatArray(
5.169 + [ 1, 1, 0, 1, 0, 0, 1, 0, // v0-v1-v2-v3 front
5.170 + 0, 1, 0, 0, 1, 0, 1, 1, // v0-v3-v4-v5 right
5.171 + 1, 0, 1, 1, 0, 1, 0, 0, // v0-v5-v6-v1 top
5.172 + 1, 1, 0, 1, 0, 0, 1, 0, // v1-v6-v7-v2 left
5.173 + 0, 0, 1, 0, 1, 1, 0, 1, // v7-v4-v3-v2 bottom
5.174 + 0, 0, 1, 0, 1, 1, 0, 1 ] // v4-v7-v6-v5 back
5.175 + );
5.176 +
5.177 + // index array
5.178 + var indices = new WebGLUnsignedByteArray(
5.179 + [ 0, 1, 2, 0, 2, 3, // front
5.180 + 4, 5, 6, 4, 6, 7, // right
5.181 + 8, 9,10, 8,10,11, // top
5.182 + 12,13,14, 12,14,15, // left
5.183 + 16,17,18, 16,18,19, // bottom
5.184 + 20,21,22, 20,22,23 ] // back
5.185 + );
5.186 +
5.187 + var retval = { };
5.188 +
5.189 + retval.normalObject = ctx.createBuffer();
5.190 + ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject);
5.191 + ctx.bufferData(ctx.ARRAY_BUFFER, normals, ctx.STATIC_DRAW);
5.192 +
5.193 + retval.texCoordObject = ctx.createBuffer();
5.194 + ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject);
5.195 + ctx.bufferData(ctx.ARRAY_BUFFER, texCoords, ctx.STATIC_DRAW);
5.196 +
5.197 + retval.vertexObject = ctx.createBuffer();
5.198 + ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject);
5.199 + ctx.bufferData(ctx.ARRAY_BUFFER, vertices, ctx.STATIC_DRAW);
5.200 +
5.201 + ctx.bindBuffer(ctx.ARRAY_BUFFER, 0);
5.202 +
5.203 + retval.indexObject = ctx.createBuffer();
5.204 + ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject);
5.205 + ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, indices, ctx.STATIC_DRAW);
5.206 + ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, 0);
5.207 +
5.208 + retval.numIndices = indices.length;
5.209 +
5.210 + return retval;
5.211 +}
5.212 +
5.213 +//
5.214 +// makeSphere
5.215 +//
5.216 +// Create a sphere with the passed number of latitude and longitude bands and the passed radius.
5.217 +// Sphere has vertices, normals and texCoords. Create VBOs for each as well as the index array.
5.218 +// Return an object with the following properties:
5.219 +//
5.220 +// normalObject WebGLBuffer object for normals
5.221 +// texCoordObject WebGLBuffer object for texCoords
5.222 +// vertexObject WebGLBuffer object for vertices
5.223 +// indexObject WebGLBuffer object for indices
5.224 +// numIndices The number of indices in the indexObject
5.225 +//
5.226 +function makeSphere(ctx, radius, lats, longs)
5.227 +{
5.228 + var geometryData = [ ];
5.229 + var normalData = [ ];
5.230 + var texCoordData = [ ];
5.231 + var indexData = [ ];
5.232 +
5.233 + for (var latNumber = 0; latNumber <= lats; ++latNumber) {
5.234 + for (var longNumber = 0; longNumber <= longs; ++longNumber) {
5.235 + var theta = latNumber * Math.PI / lats;
5.236 + var phi = longNumber * 2 * Math.PI / longs;
5.237 + var sinTheta = Math.sin(theta);
5.238 + var sinPhi = Math.sin(phi);
5.239 + var cosTheta = Math.cos(theta);
5.240 + var cosPhi = Math.cos(phi);
5.241 +
5.242 + var x = cosPhi * sinTheta;
5.243 + var y = cosTheta;
5.244 + var z = sinPhi * sinTheta;
5.245 + var u = 1-(longNumber/longs);
5.246 + var v = latNumber/lats;
5.247 +
5.248 + normalData.push(x);
5.249 + normalData.push(y);
5.250 + normalData.push(z);
5.251 + texCoordData.push(u);
5.252 + texCoordData.push(v);
5.253 + geometryData.push(radius * x);
5.254 + geometryData.push(radius * y);
5.255 + geometryData.push(radius * z);
5.256 + }
5.257 + }
5.258 +
5.259 + longs += 1;
5.260 + for (var latNumber = 0; latNumber < lats; ++latNumber) {
5.261 + for (var longNumber = 0; longNumber < longs; ++longNumber) {
5.262 + var first = (latNumber * longs) + (longNumber % longs);
5.263 + var second = first + longs;
5.264 + indexData.push(first);
5.265 + indexData.push(second);
5.266 + indexData.push(first+1);
5.267 +
5.268 + indexData.push(second);
5.269 + indexData.push(second+1);
5.270 + indexData.push(first+1);
5.271 + }
5.272 + }
5.273 +
5.274 + var retval = { };
5.275 +
5.276 + retval.normalObject = ctx.createBuffer();
5.277 + ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject);
5.278 + ctx.bufferData(ctx.ARRAY_BUFFER, new WebGLFloatArray(normalData), ctx.STATIC_DRAW);
5.279 +
5.280 + retval.texCoordObject = ctx.createBuffer();
5.281 + ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject);
5.282 + ctx.bufferData(ctx.ARRAY_BUFFER, new WebGLFloatArray(texCoordData), ctx.STATIC_DRAW);
5.283 +
5.284 + retval.vertexObject = ctx.createBuffer();
5.285 + ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject);
5.286 + ctx.bufferData(ctx.ARRAY_BUFFER, new WebGLFloatArray(geometryData), ctx.STATIC_DRAW);
5.287 +
5.288 + retval.numIndices = indexData.length;
5.289 + retval.indexObject = ctx.createBuffer();
5.290 + ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject);
5.291 + ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(indexData), ctx.STREAM_DRAW);
5.292 +
5.293 + return retval;
5.294 +}
5.295 +
5.296 +//
5.297 +// loadObj
5.298 +//
5.299 +// Load a .obj file from the passed URL. Return an object with a 'loaded' property set to false.
5.300 +// When the object load is complete, the 'loaded' property becomes true and the following
5.301 +// properties are set:
5.302 +//
5.303 +// normalObject WebGLBuffer object for normals
5.304 +// texCoordObject WebGLBuffer object for texCoords
5.305 +// vertexObject WebGLBuffer object for vertices
5.306 +// indexObject WebGLBuffer object for indices
5.307 +// numIndices The number of indices in the indexObject
5.308 +//
5.309 +function loadObj(ctx, url)
5.310 +{
5.311 + var obj = { loaded : false };
5.312 + obj.ctx = ctx;
5.313 + var req = new XMLHttpRequest();
5.314 + req.obj = obj;
5.315 + req.onreadystatechange = function () { processLoadObj(req) };
5.316 + req.open("GET", url, true);
5.317 + req.send(null);
5.318 + return obj;
5.319 +}
5.320 +
5.321 +function processLoadObj(req)
5.322 +{
5.323 + console.log("req="+req)
5.324 + // only if req shows "complete"
5.325 + if (req.readyState == 4) {
5.326 + doLoadObj(req.obj, req.responseText);
5.327 + }
5.328 +}
5.329 +
5.330 +function doLoadObj(obj, text)
5.331 +{
5.332 + vertexArray = [ ];
5.333 + normalArray = [ ];
5.334 + textureArray = [ ];
5.335 + indexArray = [ ];
5.336 +
5.337 + var vertex = [ ];
5.338 + var normal = [ ];
5.339 + var texture = [ ];
5.340 + var facemap = { };
5.341 + var index = 0;
5.342 +
5.343 + var lines = text.split("\n");
5.344 + for (var lineIndex in lines) {
5.345 + var line = lines[lineIndex].replace(/[ \t]+/g, " ").replace(/\s\s*$/, "");
5.346 +
5.347 + // ignore comments
5.348 + if (line[0] == "#")
5.349 + continue;
5.350 +
5.351 + var array = line.split(" ");
5.352 + if (array[0] == "v") {
5.353 + // vertex
5.354 + vertex.push(parseFloat(array[1]));
5.355 + vertex.push(parseFloat(array[2]));
5.356 + vertex.push(parseFloat(array[3]));
5.357 + }
5.358 + else if (array[0] == "vt") {
5.359 + // normal
5.360 + texture.push(parseFloat(array[1]));
5.361 + texture.push(parseFloat(array[2]));
5.362 + }
5.363 + else if (array[0] == "vn") {
5.364 + // normal
5.365 + normal.push(parseFloat(array[1]));
5.366 + normal.push(parseFloat(array[2]));
5.367 + normal.push(parseFloat(array[3]));
5.368 + }
5.369 + else if (array[0] == "f") {
5.370 + // face
5.371 + if (array.length != 4) {
5.372 + console.log("*** Error: face '"+line+"' not handled");
5.373 + continue;
5.374 + }
5.375 +
5.376 + for (var i = 1; i < 4; ++i) {
5.377 + if (!(array[i] in facemap)) {
5.378 + // add a new entry to the map and arrays
5.379 + var f = array[i].split("/");
5.380 + var vtx, nor, tex;
5.381 +
5.382 + if (f.length == 1) {
5.383 + vtx = parseInt(f[0]) - 1;
5.384 + nor = vtx;
5.385 + tex = vtx;
5.386 + }
5.387 + else if (f.length = 3) {
5.388 + vtx = parseInt(f[0]) - 1;
5.389 + tex = parseInt(f[1]) - 1;
5.390 + nor = parseInt(f[2]) - 1;
5.391 + }
5.392 + else {
5.393 + console.log("*** Error: did not understand face '"+array[i]+"'");
5.394 + return null;
5.395 + }
5.396 +
5.397 + // do the vertices
5.398 + var x = 0;
5.399 + var y = 0;
5.400 + var z = 0;
5.401 + if (vtx * 3 + 2 < vertex.length) {
5.402 + x = vertex[vtx*3];
5.403 + y = vertex[vtx*3+1];
5.404 + z = vertex[vtx*3+2];
5.405 + }
5.406 + vertexArray.push(x);
5.407 + vertexArray.push(y);
5.408 + vertexArray.push(z);
5.409 +
5.410 + // do the textures
5.411 + x = 0;
5.412 + y = 0;
5.413 + if (tex * 2 + 1 < texture.length) {
5.414 + x = texture[tex*2];
5.415 + y = texture[tex*2+1];
5.416 + }
5.417 + textureArray.push(x);
5.418 + textureArray.push(y);
5.419 +
5.420 + // do the normals
5.421 + x = 0;
5.422 + y = 0;
5.423 + z = 1;
5.424 + if (nor * 3 + 2 < normal.length) {
5.425 + x = normal[nor*3];
5.426 + y = normal[nor*3+1];
5.427 + z = normal[nor*3+2];
5.428 + }
5.429 + normalArray.push(x);
5.430 + normalArray.push(y);
5.431 + normalArray.push(z);
5.432 +
5.433 + facemap[array[i]] = index++;
5.434 + }
5.435 +
5.436 + indexArray.push(facemap[array[i]]);
5.437 + }
5.438 + }
5.439 + }
5.440 +
5.441 + // set the VBOs
5.442 + obj.normalObject = obj.ctx.createBuffer();
5.443 + obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.normalObject);
5.444 + obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new WebGLFloatArray(normalArray), obj.ctx.STATIC_DRAW);
5.445 +
5.446 + obj.texCoordObject = obj.ctx.createBuffer();
5.447 + obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.texCoordObject);
5.448 + obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new WebGLFloatArray(textureArray), obj.ctx.STATIC_DRAW);
5.449 +
5.450 + obj.vertexObject = obj.ctx.createBuffer();
5.451 + obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.vertexObject);
5.452 + obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new WebGLFloatArray(vertexArray), obj.ctx.STATIC_DRAW);
5.453 +
5.454 + obj.numIndices = indexArray.length;
5.455 + obj.indexObject = obj.ctx.createBuffer();
5.456 + obj.ctx.bindBuffer(obj.ctx.ELEMENT_ARRAY_BUFFER, obj.indexObject);
5.457 + obj.ctx.bufferData(obj.ctx.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(indexArray), obj.ctx.STREAM_DRAW);
5.458 +
5.459 + obj.loaded = true;
5.460 +}
5.461 +
5.462 +//
5.463 +// loadImageTexture
5.464 +//
5.465 +// Load the image at the passed url, place it in a new WebGLTexture object and return the WebGLTexture.
5.466 +//
5.467 +function loadImageTexture(ctx, url)
5.468 +{
5.469 + var texture = ctx.createTexture();
5.470 + texture.image = new Image();
5.471 + texture.image.onload = function() { doLoadImageTexture(ctx, texture.image, texture) }
5.472 + texture.image.src = url;
5.473 + return texture;
5.474 +}
5.475 +
5.476 +function doLoadImageTexture(ctx, image, texture)
5.477 +{
5.478 + ctx.enable(ctx.TEXTURE_2D);
5.479 + ctx.bindTexture(ctx.TEXTURE_2D, texture);
5.480 + ctx.texImage2D(ctx.TEXTURE_2D, 0, image);
5.481 + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR);
5.482 + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR_MIPMAP_LINEAR);
5.483 + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
5.484 + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
5.485 + ctx.generateMipmap(ctx.TEXTURE_2D)
5.486 + ctx.bindTexture(ctx.TEXTURE_2D, 0);
5.487 +}
5.488 +
5.489 +//
5.490 +// Framerate object
5.491 +//
5.492 +// This object keeps track of framerate and displays it as the innerHTML text of the
5.493 +// HTML element with the passed id. Once created you call snapshot at the end
5.494 +// of every rendering cycle. Every 500ms the framerate is updated in the HTML element.
5.495 +//
5.496 +Framerate = function(id)
5.497 +{
5.498 + this.numFramerates = 10;
5.499 + this.framerateUpdateInterval = 500;
5.500 + this.id = id;
5.501 +
5.502 + this.renderTime = -1;
5.503 + this.framerates = [ ];
5.504 + self = this;
5.505 + var fr = function() { self.updateFramerate() }
5.506 + setInterval(fr, this.framerateUpdateInterval);
5.507 +}
5.508 +
5.509 +Framerate.prototype.updateFramerate = function()
5.510 +{
5.511 + var tot = 0;
5.512 + for (var i = 0; i < this.framerates.length; ++i)
5.513 + tot += this.framerates[i];
5.514 +
5.515 + var framerate = tot / this.framerates.length;
5.516 + framerate = Math.round(framerate);
5.517 + document.getElementById(this.id).innerHTML = "Framerate:"+framerate+"fps";
5.518 +}
5.519 +
5.520 +Framerate.prototype.snapshot = function()
5.521 +{
5.522 + if (this.renderTime < 0)
5.523 + this.renderTime = new Date().getTime();
5.524 + else {
5.525 + var newTime = new Date().getTime();
5.526 + var t = newTime - this.renderTime;
5.527 + var framerate = 1000/t;
5.528 + this.framerates.push(framerate);
5.529 + while (this.framerates.length > this.numFramerates)
5.530 + this.framerates.shift();
5.531 + this.renderTime = newTime;
5.532 + }
5.533 +}
5.534 \ No newline at end of file