[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc
cmarrin at apple.com
cmarrin at apple.com
Wed Dec 22 12:44:04 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit 43b484449afbfe585268775247da0279c75599a5
Author: cmarrin at apple.com <cmarrin at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Fri Aug 27 23:36:59 2010 +0000
Forgot to add new WebGL demo support files
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66275 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitSite/blog-files/webgl/resources/J3DI.js b/WebKitSite/blog-files/webgl/resources/J3DI.js
new file mode 100644
index 0000000..b3eaf25
--- /dev/null
+++ b/WebKitSite/blog-files/webgl/resources/J3DI.js
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2009 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+//
+// initWebGL
+//
+// Initialize the Canvas element with the passed name as a WebGL object and return the
+// WebGLRenderingContext.
+//
+// Load shaders with the passed names and create a program with them. Return this program
+// in the 'program' property of the returned context.
+//
+// For each string in the passed attribs array, bind an attrib with that name at that index.
+// Once the attribs are bound, link the program and then use it.
+//
+// Set the clear color to the passed array (4 values) and set the clear depth to the passed value.
+// Enable depth testing and blending with a blend func of (SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
+//
+// A console function is added to the context: console(string). This can be replaced
+// by the caller. By default, it maps to the window.console() function on WebKit and to
+// an empty function on other browsers.
+//
+function initWebGL(canvasName, vshader, fshader, attribs, clearColor, clearDepth)
+{
+ var canvas = document.getElementById(canvasName);
+ var gl = canvas.getContext("experimental-webgl");
+ if (!gl) {
+ alert("No WebGL context found");
+ return null;
+ }
+
+ // Add a console
+ gl.console = ("console" in window) ? window.console : { log: function() { } };
+
+ // create our shaders
+ var vertexShader = loadShader(gl, vshader);
+ var fragmentShader = loadShader(gl, fshader);
+
+ if (!vertexShader || !fragmentShader)
+ return null;
+
+ // Create the program object
+ gl.program = gl.createProgram();
+
+ if (!gl.program)
+ return null;
+
+ // Attach our two shaders to the program
+ gl.attachShader (gl.program, vertexShader);
+ gl.attachShader (gl.program, fragmentShader);
+
+ // Bind attributes
+ for (var i in attribs)
+ gl.bindAttribLocation (gl.program, i, attribs[i]);
+
+ // Link the program
+ gl.linkProgram(gl.program);
+
+ // Check the link status
+ var linked = gl.getProgramParameter(gl.program, gl.LINK_STATUS);
+ if (!linked) {
+ // something went wrong with the link
+ var error = gl.getProgramInfoLog (gl.program);
+ gl.console.log("Error in program linking:"+error);
+
+ gl.deleteProgram(gl.program);
+ gl.deleteProgram(fragmentShader);
+ gl.deleteProgram(vertexShader);
+
+ return null;
+ }
+
+ gl.useProgram(gl.program);
+
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clearDepth(clearDepth);
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+
+ return gl;
+}
+
+//
+// loadShader
+//
+// 'shaderId' is the id of a <script> element containing the shader source string.
+// Load this shader and return the WebGLShader object corresponding to it.
+//
+function loadShader(ctx, shaderId)
+{
+ var shaderScript = document.getElementById(shaderId);
+ if (!shaderScript) {
+ ctx.console.log("*** Error: shader script '"+shaderId+"' not found");
+ return null;
+ }
+
+ if (shaderScript.type == "x-shader/x-vertex")
+ var shaderType = ctx.VERTEX_SHADER;
+ else if (shaderScript.type == "x-shader/x-fragment")
+ var shaderType = ctx.FRAGMENT_SHADER;
+ else {
+ ctx.console.log("*** Error: shader script '"+shaderId+"' of undefined type '"+shaderScript.type+"'");
+ return null;
+ }
+
+ // Create the shader object
+ var shader = ctx.createShader(shaderType);
+ if (shader == null) {
+ ctx.console.log("*** Error: unable to create shader '"+shaderId+"'");
+ return null;
+ }
+
+ // Load the shader source
+ ctx.shaderSource(shader, shaderScript.text);
+
+ // Compile the shader
+ ctx.compileShader(shader);
+
+ // Check the compile status
+ var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
+ if (!compiled) {
+ // Something went wrong during compilation; get the error
+ var error = ctx.getShaderInfoLog(shader);
+ ctx.console.log("*** Error compiling shader '"+shaderId+"':"+error);
+ ctx.deleteShader(shader);
+ return null;
+ }
+
+ return shader;
+}
+
+//
+// makeBox
+//
+// Create a box with vertices, normals and texCoords. Create VBOs for each as well as the index array.
+// Return an object with the following properties:
+//
+// normalObject WebGLBuffer object for normals
+// texCoordObject WebGLBuffer object for texCoords
+// vertexObject WebGLBuffer object for vertices
+// indexObject WebGLBuffer object for indices
+// numIndices The number of indices in the indexObject
+//
+function makeBox(ctx)
+{
+ // box
+ // v6----- v5
+ // /| /|
+ // v1------v0|
+ // | | | |
+ // | |v7---|-|v4
+ // |/ |/
+ // v2------v3
+ //
+ // vertex coords array
+ var vertices = new Float32Array(
+ [ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0-v1-v2-v3 front
+ 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0-v3-v4-v5 right
+ 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0-v5-v6-v1 top
+ -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1-v6-v7-v2 left
+ -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7-v4-v3-v2 bottom
+ 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 ] // v4-v7-v6-v5 back
+ );
+
+ // normal array
+ var normals = new Float32Array(
+ [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2-v3 front
+ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right
+ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0-v5-v6-v1 top
+ -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1-v6-v7-v2 left
+ 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7-v4-v3-v2 bottom
+ 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 ] // v4-v7-v6-v5 back
+ );
+
+
+ // texCoord array
+ var texCoords = new Float32Array(
+ [ 1, 1, 0, 1, 0, 0, 1, 0, // v0-v1-v2-v3 front
+ 0, 1, 0, 0, 1, 0, 1, 1, // v0-v3-v4-v5 right
+ 1, 0, 1, 1, 0, 1, 0, 0, // v0-v5-v6-v1 top
+ 1, 1, 0, 1, 0, 0, 1, 0, // v1-v6-v7-v2 left
+ 0, 0, 1, 0, 1, 1, 0, 1, // v7-v4-v3-v2 bottom
+ 0, 0, 1, 0, 1, 1, 0, 1 ] // v4-v7-v6-v5 back
+ );
+
+ // index array
+ var indices = new Uint8Array(
+ [ 0, 1, 2, 0, 2, 3, // front
+ 4, 5, 6, 4, 6, 7, // right
+ 8, 9,10, 8,10,11, // top
+ 12,13,14, 12,14,15, // left
+ 16,17,18, 16,18,19, // bottom
+ 20,21,22, 20,22,23 ] // back
+ );
+
+ var retval = { };
+
+ retval.normalObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, normals, ctx.STATIC_DRAW);
+
+ retval.texCoordObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, texCoords, ctx.STATIC_DRAW);
+
+ retval.vertexObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, vertices, ctx.STATIC_DRAW);
+
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
+
+ retval.indexObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject);
+ ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, indices, ctx.STATIC_DRAW);
+ ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
+
+ retval.numIndices = indices.length;
+
+ return retval;
+}
+
+//
+// makeSphere
+//
+// Create a sphere with the passed number of latitude and longitude bands and the passed radius.
+// Sphere has vertices, normals and texCoords. Create VBOs for each as well as the index array.
+// Return an object with the following properties:
+//
+// normalObject WebGLBuffer object for normals
+// texCoordObject WebGLBuffer object for texCoords
+// vertexObject WebGLBuffer object for vertices
+// indexObject WebGLBuffer object for indices
+// numIndices The number of indices in the indexObject
+//
+function makeSphere(ctx, radius, lats, longs)
+{
+ var geometryData = [ ];
+ var normalData = [ ];
+ var texCoordData = [ ];
+ var indexData = [ ];
+
+ for (var latNumber = 0; latNumber <= lats; ++latNumber) {
+ for (var longNumber = 0; longNumber <= longs; ++longNumber) {
+ var theta = latNumber * Math.PI / lats;
+ var phi = longNumber * 2 * Math.PI / longs;
+ var sinTheta = Math.sin(theta);
+ var sinPhi = Math.sin(phi);
+ var cosTheta = Math.cos(theta);
+ var cosPhi = Math.cos(phi);
+
+ var x = cosPhi * sinTheta;
+ var y = cosTheta;
+ var z = sinPhi * sinTheta;
+ var u = 1-(longNumber/longs);
+ var v = latNumber/lats;
+
+ normalData.push(x);
+ normalData.push(y);
+ normalData.push(z);
+ texCoordData.push(u);
+ texCoordData.push(v);
+ geometryData.push(radius * x);
+ geometryData.push(radius * y);
+ geometryData.push(radius * z);
+ }
+ }
+
+ for (var latNumber = 0; latNumber < lats; ++latNumber) {
+ for (var longNumber = 0; longNumber < longs; ++longNumber) {
+ var first = (latNumber * (longs+1)) + longNumber;
+ var second = first + longs + 1;
+ indexData.push(first);
+ indexData.push(second);
+ indexData.push(first+1);
+
+ indexData.push(second);
+ indexData.push(second+1);
+ indexData.push(first+1);
+ }
+ }
+
+ var retval = { };
+
+ retval.normalObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(normalData), ctx.STATIC_DRAW);
+
+ retval.texCoordObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(texCoordData), ctx.STATIC_DRAW);
+
+ retval.vertexObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(geometryData), ctx.STATIC_DRAW);
+
+ retval.numIndices = indexData.length;
+ retval.indexObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject);
+ ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), ctx.STREAM_DRAW);
+
+ return retval;
+}
+
+//
+// loadObj
+//
+// Load a .obj file from the passed URL. Return an object with a 'loaded' property set to false.
+// When the object load is complete, the 'loaded' property becomes true and the following
+// properties are set:
+//
+// normalObject WebGLBuffer object for normals
+// texCoordObject WebGLBuffer object for texCoords
+// vertexObject WebGLBuffer object for vertices
+// indexObject WebGLBuffer object for indices
+// numIndices The number of indices in the indexObject
+//
+function loadObj(ctx, url)
+{
+ var obj = { loaded : false };
+ obj.ctx = ctx;
+ var req = new XMLHttpRequest();
+ req.obj = obj;
+ req.onreadystatechange = function () { processLoadObj(req) };
+ req.open("GET", url, true);
+ req.send(null);
+ return obj;
+}
+
+function processLoadObj(req)
+{
+ req.obj.ctx.console.log("req="+req)
+ // only if req shows "complete"
+ if (req.readyState == 4) {
+ doLoadObj(req.obj, req.responseText);
+ }
+}
+
+function doLoadObj(obj, text)
+{
+ vertexArray = [ ];
+ normalArray = [ ];
+ textureArray = [ ];
+ indexArray = [ ];
+
+ var vertex = [ ];
+ var normal = [ ];
+ var texture = [ ];
+ var facemap = { };
+ var index = 0;
+
+ // This is a map which associates a range of indices with a name
+ // The name comes from the 'g' tag (of the form "g NAME"). Indices
+ // are part of one group until another 'g' tag is seen. If any indices
+ // come before a 'g' tag, it is given the group name "_unnamed"
+ // 'group' is an object whose property names are the group name and
+ // whose value is a 2 element array with [<first index>, <num indices>]
+ var groups = { };
+ var currentGroup = [-1, 0];
+ groups["_unnamed"] = currentGroup;
+
+ var lines = text.split("\n");
+ for (var lineIndex in lines) {
+ var line = lines[lineIndex].replace(/[ \t]+/g, " ").replace(/\s\s*$/, "");
+
+ // ignore comments
+ if (line[0] == "#")
+ continue;
+
+ var array = line.split(" ");
+ if (array[0] == "g") {
+ // new group
+ currentGroup = [indexArray.length, 0];
+ groups[array[1]] = currentGroup;
+ }
+ else if (array[0] == "v") {
+ // vertex
+ vertex.push(parseFloat(array[1]));
+ vertex.push(parseFloat(array[2]));
+ vertex.push(parseFloat(array[3]));
+ }
+ else if (array[0] == "vt") {
+ // normal
+ texture.push(parseFloat(array[1]));
+ texture.push(parseFloat(array[2]));
+ }
+ else if (array[0] == "vn") {
+ // normal
+ normal.push(parseFloat(array[1]));
+ normal.push(parseFloat(array[2]));
+ normal.push(parseFloat(array[3]));
+ }
+ else if (array[0] == "f") {
+ // face
+ if (array.length != 4) {
+ obj.ctx.console.log("*** Error: face '"+line+"' not handled");
+ continue;
+ }
+
+ for (var i = 1; i < 4; ++i) {
+ if (!(array[i] in facemap)) {
+ // add a new entry to the map and arrays
+ var f = array[i].split("/");
+ var vtx, nor, tex;
+
+ if (f.length == 1) {
+ vtx = parseInt(f[0]) - 1;
+ nor = vtx;
+ tex = vtx;
+ }
+ else if (f.length = 3) {
+ vtx = parseInt(f[0]) - 1;
+ tex = parseInt(f[1]) - 1;
+ nor = parseInt(f[2]) - 1;
+ }
+ else {
+ obj.ctx.console.log("*** Error: did not understand face '"+array[i]+"'");
+ return null;
+ }
+
+ // do the vertices
+ var x = 0;
+ var y = 0;
+ var z = 0;
+ if (vtx * 3 + 2 < vertex.length) {
+ x = vertex[vtx*3];
+ y = vertex[vtx*3+1];
+ z = vertex[vtx*3+2];
+ }
+ vertexArray.push(x);
+ vertexArray.push(y);
+ vertexArray.push(z);
+
+ // do the textures
+ x = 0;
+ y = 0;
+ if (tex * 2 + 1 < texture.length) {
+ x = texture[tex*2];
+ y = texture[tex*2+1];
+ }
+ textureArray.push(x);
+ textureArray.push(y);
+
+ // do the normals
+ x = 0;
+ y = 0;
+ z = 1;
+ if (nor * 3 + 2 < normal.length) {
+ x = normal[nor*3];
+ y = normal[nor*3+1];
+ z = normal[nor*3+2];
+ }
+ normalArray.push(x);
+ normalArray.push(y);
+ normalArray.push(z);
+
+ facemap[array[i]] = index++;
+ }
+
+ indexArray.push(facemap[array[i]]);
+ currentGroup[1]++;
+ }
+ }
+ }
+
+ // set the VBOs
+ obj.normalObject = obj.ctx.createBuffer();
+ obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.normalObject);
+ obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new Float32Array(normalArray), obj.ctx.STATIC_DRAW);
+
+ obj.texCoordObject = obj.ctx.createBuffer();
+ obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.texCoordObject);
+ obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new Float32Array(textureArray), obj.ctx.STATIC_DRAW);
+
+ obj.vertexObject = obj.ctx.createBuffer();
+ obj.ctx.bindBuffer(obj.ctx.ARRAY_BUFFER, obj.vertexObject);
+ obj.ctx.bufferData(obj.ctx.ARRAY_BUFFER, new Float32Array(vertexArray), obj.ctx.STATIC_DRAW);
+
+ obj.numIndices = indexArray.length;
+ obj.indexObject = obj.ctx.createBuffer();
+ obj.ctx.bindBuffer(obj.ctx.ELEMENT_ARRAY_BUFFER, obj.indexObject);
+ obj.ctx.bufferData(obj.ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), obj.ctx.STREAM_DRAW);
+
+ obj.groups = groups;
+
+ obj.loaded = true;
+}
+
+//
+// loadImageTexture
+//
+// Load the image at the passed url, place it in a new WebGLTexture object and return the WebGLTexture.
+//
+function loadImageTexture(ctx, url)
+{
+ var texture = ctx.createTexture();
+ texture.image = new Image();
+ texture.image.onload = function() { doLoadImageTexture(ctx, texture.image, texture) }
+ texture.image.src = url;
+ return texture;
+}
+
+function doLoadImageTexture(ctx, image, texture)
+{
+ ctx.bindTexture(ctx.TEXTURE_2D, texture);
+ ctx.texImage2D(
+ ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image);
+ ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR);
+ ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR);
+ ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
+ ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
+ //ctx.generateMipmap(ctx.TEXTURE_2D)
+ ctx.bindTexture(ctx.TEXTURE_2D, null);
+}
+
+//
+// Framerate object
+//
+// This object keeps track of framerate and displays it as the innerHTML text of the
+// HTML element with the passed id. Once created you call snapshot at the end
+// of every rendering cycle. Every 500ms the framerate is updated in the HTML element.
+//
+Framerate = function(id)
+{
+ this.numFramerates = 10;
+ this.framerateUpdateInterval = 500;
+ this.id = id;
+
+ this.renderTime = -1;
+ this.framerates = [ ];
+ self = this;
+ var fr = function() { self.updateFramerate() }
+ setInterval(fr, this.framerateUpdateInterval);
+}
+
+Framerate.prototype.updateFramerate = function()
+{
+ var tot = 0;
+ for (var i = 0; i < this.framerates.length; ++i)
+ tot += this.framerates[i];
+
+ var framerate = tot / this.framerates.length;
+ framerate = Math.round(framerate);
+ document.getElementById(this.id).innerHTML = "Framerate:"+framerate+"fps";
+}
+
+Framerate.prototype.snapshot = function()
+{
+ if (this.renderTime < 0)
+ this.renderTime = new Date().getTime();
+ else {
+ var newTime = new Date().getTime();
+ var t = newTime - this.renderTime;
+ var framerate = 1000/t;
+ this.framerates.push(framerate);
+ while (this.framerates.length > this.numFramerates)
+ this.framerates.shift();
+ this.renderTime = newTime;
+ }
+}
diff --git a/WebKitSite/blog-files/webgl/resources/J3DIMath.js b/WebKitSite/blog-files/webgl/resources/J3DIMath.js
new file mode 100644
index 0000000..b3e5b64
--- /dev/null
+++ b/WebKitSite/blog-files/webgl/resources/J3DIMath.js
@@ -0,0 +1,1065 @@
+/*
+ * Copyright (C) 2009 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+ // J3DI (Jedi) - A support library for WebGL.
+
+/*
+ J3DI Math Classes. Currently includes:
+
+ J3DIMatrix4 - A 4x4 Matrix
+*/
+
+/*
+ J3DIMatrix4 class
+
+ This class implements a 4x4 matrix. It has functions which duplicate the
+ functionality of the OpenGL matrix stack and glut functions. On browsers
+ that support it, CSSMatrix is used to accelerate operations.
+
+ IDL:
+
+ [
+ Constructor(in J3DIMatrix4 matrix), // copy passed matrix into new J3DIMatrix4
+ Constructor(in sequence<float> array) // create new J3DIMatrix4 with 16 floats (row major)
+ Constructor() // create new J3DIMatrix4 with identity matrix
+ ]
+ interface J3DIMatrix4 {
+ void load(in J3DIMatrix4 matrix); // copy the values from the passed matrix
+ void load(in sequence<float> array); // copy 16 floats into the matrix
+ sequence<float> getAsArray(); // return the matrix as an array of 16 floats
+ Float32Array getAsFloat32Array(); // return the matrix as a Float32Array with 16 values
+ void setUniform(in WebGLRenderingContext ctx, // Send the matrix to the passed uniform location in the passed context
+ in WebGLUniformLocation loc,
+ in boolean transpose);
+ void makeIdentity(); // replace the matrix with identity
+ void transpose(); // replace the matrix with its transpose
+ void invert(); // replace the matrix with its inverse
+
+ void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right
+ void translate(in J3DVector3 v); // multiply the matrix by passed translation values on the right
+ void scale(in float x, in float y, in float z); // multiply the matrix by passed scale values on the right
+ void scale(in J3DVector3 v); // multiply the matrix by passed scale values on the right
+ void rotate(in float angle, // multiply the matrix by passed rotation values on the right
+ in float x, in float y, in float z); // (angle is in degrees)
+ void rotate(in float angle, in J3DVector3 v); // multiply the matrix by passed rotation values on the right
+ // (angle is in degrees)
+ void multiply(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the right
+ void divide(in float divisor); // divide the matrix by the passed divisor
+ void ortho(in float left, in float right, // multiply the matrix by the passed ortho values on the right
+ in float bottom, in float top,
+ in float near, in float far);
+ void frustum(in float left, in float right, // multiply the matrix by the passed frustum values on the right
+ in float bottom, in float top,
+ in float near, in float far);
+ void perspective(in float fovy, in float aspect, // multiply the matrix by the passed perspective values on the right
+ in float zNear, in float zFar);
+ void lookat(in J3DVector3 eye, // multiply the matrix by the passed lookat
+ in J3DVector3 center, in J3DVector3 up); // values on the right
+ bool decompose(in J3DVector3 translate, // decompose the matrix into the passed vector
+ in J3DVector3 rotate,
+ in J3DVector3 scale,
+ in J3DVector3 skew,
+ in sequence<float> perspective);
+ }
+
+ [
+ Constructor(in J3DVector3 vector), // copy passed vector into new J3DVector3
+ Constructor(in sequence<float> array) // create new J3DVector3 with 3 floats from array
+ Constructor(in float x, in float y, in float z) // create new J3DVector3 with 3 floats
+ Constructor() // create new J3DVector3 with (0,0,0)
+ ]
+ interface J3DVector3 {
+ void load(in J3DVector3 vector); // copy the values from the passed vector
+ void load(in sequence<float> array); // copy 3 floats into the vector from array
+ void load(in float x, in float y, in float z); // copy 3 floats into the vector
+ sequence<float> getAsArray(); // return the vector as an array of 3 floats
+ Float32Array getAsFloat32Array(); // return the matrix as a Float32Array with 16 values
+ void multMatrix(in J3DIMatrix4 matrix); // multiply the vector by the passed matrix (on the right)
+ float vectorLength(); // return the length of the vector
+ float dot(); // return the dot product of the vector
+ void cross(in J3DVector3 v); // replace the vector with vector x v
+ void divide(in float divisor); // divide the vector by the passed divisor
+ }
+*/
+
+J3DIHasCSSMatrix = false;
+J3DIHasCSSMatrixCopy = false;
+/*
+if ("WebKitCSSMatrix" in window && ("media" in window && window.media.matchMedium("(-webkit-transform-3d)")) ||
+ ("styleMedia" in window && window.styleMedia.matchMedium("(-webkit-transform-3d)"))) {
+ J3DIHasCSSMatrix = true;
+ if ("copy" in WebKitCSSMatrix.prototype)
+ J3DIHasCSSMatrixCopy = true;
+}
+*/
+
+// console.log("J3DIHasCSSMatrix="+J3DIHasCSSMatrix);
+// console.log("J3DIHasCSSMatrixCopy="+J3DIHasCSSMatrixCopy);
+
+//
+// J3DIMatrix4
+//
+J3DIMatrix4 = function(m)
+{
+ if (J3DIHasCSSMatrix)
+ this.$matrix = new WebKitCSSMatrix;
+ else
+ this.$matrix = new Object;
+
+ if (typeof m == 'object') {
+ if ("length" in m && m.length >= 16) {
+ this.load(m);
+ return;
+ }
+ else if (m instanceof J3DIMatrix4) {
+ this.load(m);
+ return;
+ }
+ }
+ this.makeIdentity();
+}
+
+J3DIMatrix4.prototype.load = function()
+{
+ if (arguments.length == 1 && typeof arguments[0] == 'object') {
+ var matrix;
+
+ if (arguments[0] instanceof J3DIMatrix4) {
+ matrix = arguments[0].$matrix;
+
+ this.$matrix.m11 = matrix.m11;
+ this.$matrix.m12 = matrix.m12;
+ this.$matrix.m13 = matrix.m13;
+ this.$matrix.m14 = matrix.m14;
+
+ this.$matrix.m21 = matrix.m21;
+ this.$matrix.m22 = matrix.m22;
+ this.$matrix.m23 = matrix.m23;
+ this.$matrix.m24 = matrix.m24;
+
+ this.$matrix.m31 = matrix.m31;
+ this.$matrix.m32 = matrix.m32;
+ this.$matrix.m33 = matrix.m33;
+ this.$matrix.m34 = matrix.m34;
+
+ this.$matrix.m41 = matrix.m41;
+ this.$matrix.m42 = matrix.m42;
+ this.$matrix.m43 = matrix.m43;
+ this.$matrix.m44 = matrix.m44;
+ return;
+ }
+ else
+ matrix = arguments[0];
+
+ if ("length" in matrix && matrix.length >= 16) {
+ this.$matrix.m11 = matrix[0];
+ this.$matrix.m12 = matrix[1];
+ this.$matrix.m13 = matrix[2];
+ this.$matrix.m14 = matrix[3];
+
+ this.$matrix.m21 = matrix[4];
+ this.$matrix.m22 = matrix[5];
+ this.$matrix.m23 = matrix[6];
+ this.$matrix.m24 = matrix[7];
+
+ this.$matrix.m31 = matrix[8];
+ this.$matrix.m32 = matrix[9];
+ this.$matrix.m33 = matrix[10];
+ this.$matrix.m34 = matrix[11];
+
+ this.$matrix.m41 = matrix[12];
+ this.$matrix.m42 = matrix[13];
+ this.$matrix.m43 = matrix[14];
+ this.$matrix.m44 = matrix[15];
+ return;
+ }
+ }
+
+ this.makeIdentity();
+}
+
+J3DIMatrix4.prototype.getAsArray = function()
+{
+ return [
+ this.$matrix.m11, this.$matrix.m12, this.$matrix.m13, this.$matrix.m14,
+ this.$matrix.m21, this.$matrix.m22, this.$matrix.m23, this.$matrix.m24,
+ this.$matrix.m31, this.$matrix.m32, this.$matrix.m33, this.$matrix.m34,
+ this.$matrix.m41, this.$matrix.m42, this.$matrix.m43, this.$matrix.m44
+ ];
+}
+
+J3DIMatrix4.prototype.getAsFloat32Array = function()
+{
+ if (J3DIHasCSSMatrixCopy) {
+ var array = new Float32Array(16);
+ this.$matrix.copy(array);
+ return array;
+ }
+ return new Float32Array(this.getAsArray());
+}
+
+J3DIMatrix4.prototype.setUniform = function(ctx, loc, transpose)
+{
+ if (J3DIMatrix4.setUniformArray == undefined) {
+ J3DIMatrix4.setUniformWebGLArray = new Float32Array(16);
+ J3DIMatrix4.setUniformArray = new Array(16);
+ }
+
+ if (J3DIHasCSSMatrixCopy)
+ this.$matrix.copy(J3DIMatrix4.setUniformWebGLArray);
+ else {
+ J3DIMatrix4.setUniformArray[0] = this.$matrix.m11;
+ J3DIMatrix4.setUniformArray[1] = this.$matrix.m12;
+ J3DIMatrix4.setUniformArray[2] = this.$matrix.m13;
+ J3DIMatrix4.setUniformArray[3] = this.$matrix.m14;
+ J3DIMatrix4.setUniformArray[4] = this.$matrix.m21;
+ J3DIMatrix4.setUniformArray[5] = this.$matrix.m22;
+ J3DIMatrix4.setUniformArray[6] = this.$matrix.m23;
+ J3DIMatrix4.setUniformArray[7] = this.$matrix.m24;
+ J3DIMatrix4.setUniformArray[8] = this.$matrix.m31;
+ J3DIMatrix4.setUniformArray[9] = this.$matrix.m32;
+ J3DIMatrix4.setUniformArray[10] = this.$matrix.m33;
+ J3DIMatrix4.setUniformArray[11] = this.$matrix.m34;
+ J3DIMatrix4.setUniformArray[12] = this.$matrix.m41;
+ J3DIMatrix4.setUniformArray[13] = this.$matrix.m42;
+ J3DIMatrix4.setUniformArray[14] = this.$matrix.m43;
+ J3DIMatrix4.setUniformArray[15] = this.$matrix.m44;
+
+ J3DIMatrix4.setUniformWebGLArray.set(J3DIMatrix4.setUniformArray);
+ }
+
+ ctx.uniformMatrix4fv(loc, transpose, J3DIMatrix4.setUniformWebGLArray);
+}
+
+J3DIMatrix4.prototype.makeIdentity = function()
+{
+ this.$matrix.m11 = 1;
+ this.$matrix.m12 = 0;
+ this.$matrix.m13 = 0;
+ this.$matrix.m14 = 0;
+
+ this.$matrix.m21 = 0;
+ this.$matrix.m22 = 1;
+ this.$matrix.m23 = 0;
+ this.$matrix.m24 = 0;
+
+ this.$matrix.m31 = 0;
+ this.$matrix.m32 = 0;
+ this.$matrix.m33 = 1;
+ this.$matrix.m34 = 0;
+
+ this.$matrix.m41 = 0;
+ this.$matrix.m42 = 0;
+ this.$matrix.m43 = 0;
+ this.$matrix.m44 = 1;
+}
+
+J3DIMatrix4.prototype.transpose = function()
+{
+ var tmp = this.$matrix.m12;
+ this.$matrix.m12 = this.$matrix.m21;
+ this.$matrix.m21 = tmp;
+
+ tmp = this.$matrix.m13;
+ this.$matrix.m13 = this.$matrix.m31;
+ this.$matrix.m31 = tmp;
+
+ tmp = this.$matrix.m14;
+ this.$matrix.m14 = this.$matrix.m41;
+ this.$matrix.m41 = tmp;
+
+ tmp = this.$matrix.m23;
+ this.$matrix.m23 = this.$matrix.m32;
+ this.$matrix.m32 = tmp;
+
+ tmp = this.$matrix.m24;
+ this.$matrix.m24 = this.$matrix.m42;
+ this.$matrix.m42 = tmp;
+
+ tmp = this.$matrix.m34;
+ this.$matrix.m34 = this.$matrix.m43;
+ this.$matrix.m43 = tmp;
+}
+
+J3DIMatrix4.prototype.invert = function()
+{
+ if (J3DIHasCSSMatrix) {
+ this.$matrix = this.$matrix.inverse();
+ return;
+ }
+
+ // Calculate the 4x4 determinant
+ // If the determinant is zero,
+ // then the inverse matrix is not unique.
+ var det = this._determinant4x4();
+
+ if (Math.abs(det) < 1e-8)
+ return null;
+
+ this._makeAdjoint();
+
+ // Scale the adjoint matrix to get the inverse
+ this.$matrix.m11 /= det;
+ this.$matrix.m12 /= det;
+ this.$matrix.m13 /= det;
+ this.$matrix.m14 /= det;
+
+ this.$matrix.m21 /= det;
+ this.$matrix.m22 /= det;
+ this.$matrix.m23 /= det;
+ this.$matrix.m24 /= det;
+
+ this.$matrix.m31 /= det;
+ this.$matrix.m32 /= det;
+ this.$matrix.m33 /= det;
+ this.$matrix.m34 /= det;
+
+ this.$matrix.m41 /= det;
+ this.$matrix.m42 /= det;
+ this.$matrix.m43 /= det;
+ this.$matrix.m44 /= det;
+}
+
+J3DIMatrix4.prototype.translate = function(x,y,z)
+{
+ if (typeof x == 'object' && "length" in x) {
+ var t = x;
+ x = t[0];
+ y = t[1];
+ z = t[2];
+ }
+ else {
+ if (x == undefined)
+ x = 0;
+ if (y == undefined)
+ y = 0;
+ if (z == undefined)
+ z = 0;
+ }
+
+ if (J3DIHasCSSMatrix) {
+ this.$matrix = this.$matrix.translate(x, y, z);
+ return;
+ }
+
+ var matrix = new J3DIMatrix4();
+ matrix.$matrix.m41 = x;
+ matrix.$matrix.m42 = y;
+ matrix.$matrix.m43 = z;
+
+ this.multiply(matrix);
+}
+
+J3DIMatrix4.prototype.scale = function(x,y,z)
+{
+ if (typeof x == 'object' && "length" in x) {
+ var t = x;
+ x = t[0];
+ y = t[1];
+ z = t[2];
+ }
+ else {
+ if (x == undefined)
+ x = 1;
+ if (z == undefined) {
+ if (y == undefined) {
+ y = x;
+ z = x;
+ }
+ else
+ z = 1;
+ }
+ else if (y == undefined)
+ y = x;
+ }
+
+ if (J3DIHasCSSMatrix) {
+ this.$matrix = this.$matrix.scale(x, y, z);
+ return;
+ }
+
+ var matrix = new J3DIMatrix4();
+ matrix.$matrix.m11 = x;
+ matrix.$matrix.m22 = y;
+ matrix.$matrix.m33 = z;
+
+ this.multiply(matrix);
+}
+
+J3DIMatrix4.prototype.rotate = function(angle,x,y,z)
+{
+ // Forms are (angle, x,y,z), (angle,vector), (angleX, angleY, angleZ), (angle)
+ if (typeof x == 'object' && "length" in x) {
+ var t = x;
+ x = t[0];
+ y = t[1];
+ z = t[2];
+ }
+ else {
+ if (arguments.length == 1) {
+ x = 0;
+ y = 0;
+ z = 1;
+ }
+ else if (arguments.length == 3) {
+ this.rotate(angle, 1,0,0); // about X axis
+ this.rotate(x, 0,1,0); // about Y axis
+ this.rotate(y, 0,0,1); // about Z axis
+ return;
+ }
+ }
+
+ if (J3DIHasCSSMatrix) {
+ this.$matrix = this.$matrix.rotateAxisAngle(x, y, z, angle);
+ return;
+ }
+
+ // angles are in degrees. Switch to radians
+ angle = angle / 180 * Math.PI;
+
+ angle /= 2;
+ var sinA = Math.sin(angle);
+ var cosA = Math.cos(angle);
+ var sinA2 = sinA * sinA;
+
+ // normalize
+ var len = Math.sqrt(x * x + y * y + z * z);
+ if (len == 0) {
+ // bad vector, just use something reasonable
+ x = 0;
+ y = 0;
+ z = 1;
+ } else if (len != 1) {
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+
+ var mat = new J3DIMatrix4();
+
+ // optimize case where axis is along major axis
+ if (x == 1 && y == 0 && z == 0) {
+ mat.$matrix.m11 = 1;
+ mat.$matrix.m12 = 0;
+ mat.$matrix.m13 = 0;
+ mat.$matrix.m21 = 0;
+ mat.$matrix.m22 = 1 - 2 * sinA2;
+ mat.$matrix.m23 = 2 * sinA * cosA;
+ mat.$matrix.m31 = 0;
+ mat.$matrix.m32 = -2 * sinA * cosA;
+ mat.$matrix.m33 = 1 - 2 * sinA2;
+ mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
+ mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
+ mat.$matrix.m44 = 1;
+ } else if (x == 0 && y == 1 && z == 0) {
+ mat.$matrix.m11 = 1 - 2 * sinA2;
+ mat.$matrix.m12 = 0;
+ mat.$matrix.m13 = -2 * sinA * cosA;
+ mat.$matrix.m21 = 0;
+ mat.$matrix.m22 = 1;
+ mat.$matrix.m23 = 0;
+ mat.$matrix.m31 = 2 * sinA * cosA;
+ mat.$matrix.m32 = 0;
+ mat.$matrix.m33 = 1 - 2 * sinA2;
+ mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
+ mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
+ mat.$matrix.m44 = 1;
+ } else if (x == 0 && y == 0 && z == 1) {
+ mat.$matrix.m11 = 1 - 2 * sinA2;
+ mat.$matrix.m12 = 2 * sinA * cosA;
+ mat.$matrix.m13 = 0;
+ mat.$matrix.m21 = -2 * sinA * cosA;
+ mat.$matrix.m22 = 1 - 2 * sinA2;
+ mat.$matrix.m23 = 0;
+ mat.$matrix.m31 = 0;
+ mat.$matrix.m32 = 0;
+ mat.$matrix.m33 = 1;
+ mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
+ mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
+ mat.$matrix.m44 = 1;
+ } else {
+ var x2 = x*x;
+ var y2 = y*y;
+ var z2 = z*z;
+
+ mat.$matrix.m11 = 1 - 2 * (y2 + z2) * sinA2;
+ mat.$matrix.m12 = 2 * (x * y * sinA2 + z * sinA * cosA);
+ mat.$matrix.m13 = 2 * (x * z * sinA2 - y * sinA * cosA);
+ mat.$matrix.m21 = 2 * (y * x * sinA2 - z * sinA * cosA);
+ mat.$matrix.m22 = 1 - 2 * (z2 + x2) * sinA2;
+ mat.$matrix.m23 = 2 * (y * z * sinA2 + x * sinA * cosA);
+ mat.$matrix.m31 = 2 * (z * x * sinA2 + y * sinA * cosA);
+ mat.$matrix.m32 = 2 * (z * y * sinA2 - x * sinA * cosA);
+ mat.$matrix.m33 = 1 - 2 * (x2 + y2) * sinA2;
+ mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
+ mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
+ mat.$matrix.m44 = 1;
+ }
+ this.multiply(mat);
+}
+
+J3DIMatrix4.prototype.multiply = function(mat)
+{
+ if (J3DIHasCSSMatrix) {
+ this.$matrix = this.$matrix.multiply(mat.$matrix);
+ return;
+ }
+
+ var m11 = (mat.$matrix.m11 * this.$matrix.m11 + mat.$matrix.m12 * this.$matrix.m21
+ + mat.$matrix.m13 * this.$matrix.m31 + mat.$matrix.m14 * this.$matrix.m41);
+ var m12 = (mat.$matrix.m11 * this.$matrix.m12 + mat.$matrix.m12 * this.$matrix.m22
+ + mat.$matrix.m13 * this.$matrix.m32 + mat.$matrix.m14 * this.$matrix.m42);
+ var m13 = (mat.$matrix.m11 * this.$matrix.m13 + mat.$matrix.m12 * this.$matrix.m23
+ + mat.$matrix.m13 * this.$matrix.m33 + mat.$matrix.m14 * this.$matrix.m43);
+ var m14 = (mat.$matrix.m11 * this.$matrix.m14 + mat.$matrix.m12 * this.$matrix.m24
+ + mat.$matrix.m13 * this.$matrix.m34 + mat.$matrix.m14 * this.$matrix.m44);
+
+ var m21 = (mat.$matrix.m21 * this.$matrix.m11 + mat.$matrix.m22 * this.$matrix.m21
+ + mat.$matrix.m23 * this.$matrix.m31 + mat.$matrix.m24 * this.$matrix.m41);
+ var m22 = (mat.$matrix.m21 * this.$matrix.m12 + mat.$matrix.m22 * this.$matrix.m22
+ + mat.$matrix.m23 * this.$matrix.m32 + mat.$matrix.m24 * this.$matrix.m42);
+ var m23 = (mat.$matrix.m21 * this.$matrix.m13 + mat.$matrix.m22 * this.$matrix.m23
+ + mat.$matrix.m23 * this.$matrix.m33 + mat.$matrix.m24 * this.$matrix.m43);
+ var m24 = (mat.$matrix.m21 * this.$matrix.m14 + mat.$matrix.m22 * this.$matrix.m24
+ + mat.$matrix.m23 * this.$matrix.m34 + mat.$matrix.m24 * this.$matrix.m44);
+
+ var m31 = (mat.$matrix.m31 * this.$matrix.m11 + mat.$matrix.m32 * this.$matrix.m21
+ + mat.$matrix.m33 * this.$matrix.m31 + mat.$matrix.m34 * this.$matrix.m41);
+ var m32 = (mat.$matrix.m31 * this.$matrix.m12 + mat.$matrix.m32 * this.$matrix.m22
+ + mat.$matrix.m33 * this.$matrix.m32 + mat.$matrix.m34 * this.$matrix.m42);
+ var m33 = (mat.$matrix.m31 * this.$matrix.m13 + mat.$matrix.m32 * this.$matrix.m23
+ + mat.$matrix.m33 * this.$matrix.m33 + mat.$matrix.m34 * this.$matrix.m43);
+ var m34 = (mat.$matrix.m31 * this.$matrix.m14 + mat.$matrix.m32 * this.$matrix.m24
+ + mat.$matrix.m33 * this.$matrix.m34 + mat.$matrix.m34 * this.$matrix.m44);
+
+ var m41 = (mat.$matrix.m41 * this.$matrix.m11 + mat.$matrix.m42 * this.$matrix.m21
+ + mat.$matrix.m43 * this.$matrix.m31 + mat.$matrix.m44 * this.$matrix.m41);
+ var m42 = (mat.$matrix.m41 * this.$matrix.m12 + mat.$matrix.m42 * this.$matrix.m22
+ + mat.$matrix.m43 * this.$matrix.m32 + mat.$matrix.m44 * this.$matrix.m42);
+ var m43 = (mat.$matrix.m41 * this.$matrix.m13 + mat.$matrix.m42 * this.$matrix.m23
+ + mat.$matrix.m43 * this.$matrix.m33 + mat.$matrix.m44 * this.$matrix.m43);
+ var m44 = (mat.$matrix.m41 * this.$matrix.m14 + mat.$matrix.m42 * this.$matrix.m24
+ + mat.$matrix.m43 * this.$matrix.m34 + mat.$matrix.m44 * this.$matrix.m44);
+
+ this.$matrix.m11 = m11;
+ this.$matrix.m12 = m12;
+ this.$matrix.m13 = m13;
+ this.$matrix.m14 = m14;
+
+ this.$matrix.m21 = m21;
+ this.$matrix.m22 = m22;
+ this.$matrix.m23 = m23;
+ this.$matrix.m24 = m24;
+
+ this.$matrix.m31 = m31;
+ this.$matrix.m32 = m32;
+ this.$matrix.m33 = m33;
+ this.$matrix.m34 = m34;
+
+ this.$matrix.m41 = m41;
+ this.$matrix.m42 = m42;
+ this.$matrix.m43 = m43;
+ this.$matrix.m44 = m44;
+}
+
+J3DIMatrix4.prototype.divide = function(divisor)
+{
+ this.$matrix.m11 /= divisor;
+ this.$matrix.m12 /= divisor;
+ this.$matrix.m13 /= divisor;
+ this.$matrix.m14 /= divisor;
+
+ this.$matrix.m21 /= divisor;
+ this.$matrix.m22 /= divisor;
+ this.$matrix.m23 /= divisor;
+ this.$matrix.m24 /= divisor;
+
+ this.$matrix.m31 /= divisor;
+ this.$matrix.m32 /= divisor;
+ this.$matrix.m33 /= divisor;
+ this.$matrix.m34 /= divisor;
+
+ this.$matrix.m41 /= divisor;
+ this.$matrix.m42 /= divisor;
+ this.$matrix.m43 /= divisor;
+ this.$matrix.m44 /= divisor;
+
+}
+
+J3DIMatrix4.prototype.ortho = function(left, right, bottom, top, near, far)
+{
+ var tx = (left + right) / (left - right);
+ var ty = (top + bottom) / (top - bottom);
+ var tz = (far + near) / (far - near);
+
+ var matrix = new J3DIMatrix4();
+ matrix.$matrix.m11 = 2 / (left - right);
+ matrix.$matrix.m12 = 0;
+ matrix.$matrix.m13 = 0;
+ matrix.$matrix.m14 = 0;
+ matrix.$matrix.m21 = 0;
+ matrix.$matrix.m22 = 2 / (top - bottom);
+ matrix.$matrix.m23 = 0;
+ matrix.$matrix.m24 = 0;
+ matrix.$matrix.m31 = 0;
+ matrix.$matrix.m32 = 0;
+ matrix.$matrix.m33 = -2 / (far - near);
+ matrix.$matrix.m34 = 0;
+ matrix.$matrix.m41 = tx;
+ matrix.$matrix.m42 = ty;
+ matrix.$matrix.m43 = tz;
+ matrix.$matrix.m44 = 1;
+
+ this.multiply(matrix);
+}
+
+J3DIMatrix4.prototype.frustum = function(left, right, bottom, top, near, far)
+{
+ var matrix = new J3DIMatrix4();
+ var A = (right + left) / (right - left);
+ var B = (top + bottom) / (top - bottom);
+ var C = -(far + near) / (far - near);
+ var D = -(2 * far * near) / (far - near);
+
+ matrix.$matrix.m11 = (2 * near) / (right - left);
+ matrix.$matrix.m12 = 0;
+ matrix.$matrix.m13 = 0;
+ matrix.$matrix.m14 = 0;
+
+ matrix.$matrix.m21 = 0;
+ matrix.$matrix.m22 = 2 * near / (top - bottom);
+ matrix.$matrix.m23 = 0;
+ matrix.$matrix.m24 = 0;
+
+ matrix.$matrix.m31 = A;
+ matrix.$matrix.m32 = B;
+ matrix.$matrix.m33 = C;
+ matrix.$matrix.m34 = -1;
+
+ matrix.$matrix.m41 = 0;
+ matrix.$matrix.m42 = 0;
+ matrix.$matrix.m43 = D;
+ matrix.$matrix.m44 = 0;
+
+ this.multiply(matrix);
+}
+
+J3DIMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar)
+{
+ var top = Math.tan(fovy * Math.PI / 360) * zNear;
+ var bottom = -top;
+ var left = aspect * bottom;
+ var right = aspect * top;
+ this.frustum(left, right, bottom, top, zNear, zFar);
+}
+
+J3DIMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
+{
+ if (typeof eyez == 'object' && "length" in eyez) {
+ var t = eyez;
+ upx = t[0];
+ upy = t[1];
+ upz = t[2];
+
+ t = eyey;
+ centerx = t[0];
+ centery = t[1];
+ centerz = t[2];
+
+ t = eyex;
+ eyex = t[0];
+ eyey = t[1];
+ eyez = t[2];
+ }
+
+ var matrix = new J3DIMatrix4();
+
+ // Make rotation matrix
+
+ // Z vector
+ var zx = eyex - centerx;
+ var zy = eyey - centery;
+ var zz = eyez - centerz;
+ var mag = Math.sqrt(zx * zx + zy * zy + zz * zz);
+ if (mag) {
+ zx /= mag;
+ zy /= mag;
+ zz /= mag;
+ }
+
+ // Y vector
+ var yx = upx;
+ var yy = upy;
+ var yz = upz;
+
+ // X vector = Y cross Z
+ xx = yy * zz - yz * zy;
+ xy = -yx * zz + yz * zx;
+ xz = yx * zy - yy * zx;
+
+ // Recompute Y = Z cross X
+ yx = zy * xz - zz * xy;
+ yy = -zx * xz + zz * xx;
+ yx = zx * xy - zy * xx;
+
+ // cross product gives area of parallelogram, which is < 1.0 for
+ // non-perpendicular unit-length vectors; so normalize x, y here
+
+ mag = Math.sqrt(xx * xx + xy * xy + xz * xz);
+ if (mag) {
+ xx /= mag;
+ xy /= mag;
+ xz /= mag;
+ }
+
+ mag = Math.sqrt(yx * yx + yy * yy + yz * yz);
+ if (mag) {
+ yx /= mag;
+ yy /= mag;
+ yz /= mag;
+ }
+
+ matrix.$matrix.m11 = xx;
+ matrix.$matrix.m12 = xy;
+ matrix.$matrix.m13 = xz;
+ matrix.$matrix.m14 = 0;
+
+ matrix.$matrix.m21 = yx;
+ matrix.$matrix.m22 = yy;
+ matrix.$matrix.m23 = yz;
+ matrix.$matrix.m24 = 0;
+
+ matrix.$matrix.m31 = zx;
+ matrix.$matrix.m32 = zy;
+ matrix.$matrix.m33 = zz;
+ matrix.$matrix.m34 = 0;
+
+ matrix.$matrix.m41 = 0;
+ matrix.$matrix.m42 = 0;
+ matrix.$matrix.m43 = 0;
+ matrix.$matrix.m44 = 1;
+ matrix.translate(-eyex, -eyey, -eyez);
+
+ this.multiply(matrix);
+}
+
+// Returns true on success, false otherwise. All params are Array objects
+J3DIMatrix4.prototype.decompose = function(_translate, _rotate, _scale, _skew, _perspective)
+{
+ // Normalize the matrix.
+ if (this.$matrix.m44 == 0)
+ return false;
+
+ // Gather the params
+ var translate, rotate, scale, skew, perspective;
+
+ var translate = (_translate == undefined || !("length" in _translate)) ? new J3DIVector3 : _translate;
+ var rotate = (_rotate == undefined || !("length" in _rotate)) ? new J3DIVector3 : _rotate;
+ var scale = (_scale == undefined || !("length" in _scale)) ? new J3DIVector3 : _scale;
+ var skew = (_skew == undefined || !("length" in _skew)) ? new J3DIVector3 : _skew;
+ var perspective = (_perspective == undefined || !("length" in _perspective)) ? new Array(4) : _perspective;
+
+ var matrix = new J3DIMatrix4(this);
+
+ matrix.divide(matrix.$matrix.m44);
+
+ // perspectiveMatrix is used to solve for perspective, but it also provides
+ // an easy way to test for singularity of the upper 3x3 component.
+ var perspectiveMatrix = new J3DIMatrix4(matrix);
+
+ perspectiveMatrix.$matrix.m14 = 0;
+ perspectiveMatrix.$matrix.m24 = 0;
+ perspectiveMatrix.$matrix.m34 = 0;
+ perspectiveMatrix.$matrix.m44 = 1;
+
+ if (perspectiveMatrix._determinant4x4() == 0)
+ return false;
+
+ // First, isolate perspective.
+ if (matrix.$matrix.m14 != 0 || matrix.$matrix.m24 != 0 || matrix.$matrix.m34 != 0) {
+ // rightHandSide is the right hand side of the equation.
+ var rightHandSide = [ matrix.$matrix.m14, matrix.$matrix.m24, matrix.$matrix.m34, matrix.$matrix.m44 ];
+
+ // Solve the equation by inverting perspectiveMatrix and multiplying
+ // rightHandSide by the inverse.
+ var inversePerspectiveMatrix = new J3DIMatrix4(perspectiveMatrix);
+ inversePerspectiveMatrix.invert();
+ var transposedInversePerspectiveMatrix = new J3DIMatrix4(inversePerspectiveMatrix);
+ transposedInversePerspectiveMatrix.transpose();
+ transposedInversePerspectiveMatrix.multVecMatrix(perspective, rightHandSide);
+
+ // Clear the perspective partition
+ matrix.$matrix.m14 = matrix.$matrix.m24 = matrix.$matrix.m34 = 0
+ matrix.$matrix.m44 = 1;
+ }
+ else {
+ // No perspective.
+ perspective[0] = perspective[1] = perspective[2] = 0;
+ perspective[3] = 1;
+ }
+
+ // Next take care of translation
+ translate[0] = matrix.$matrix.m41
+ matrix.$matrix.m41 = 0
+ translate[1] = matrix.$matrix.m42
+ matrix.$matrix.m42 = 0
+ translate[2] = matrix.$matrix.m43
+ matrix.$matrix.m43 = 0
+
+ // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
+ var row0 = new J3DIVector3(matrix.$matrix.m11, matrix.$matrix.m12, matrix.$matrix.m13);
+ var row1 = new J3DIVector3(matrix.$matrix.m21, matrix.$matrix.m22, matrix.$matrix.m23);
+ var row2 = new J3DIVector3(matrix.$matrix.m31, matrix.$matrix.m32, matrix.$matrix.m33);
+
+ // Compute X scale factor and normalize first row.
+ scale[0] = row0.vectorLength();
+ row0.divide(scale[0]);
+
+ // Compute XY shear factor and make 2nd row orthogonal to 1st.
+ skew[0] = row0.dot(row1);
+ row1.combine(row0, 1.0, -skew[0]);
+
+ // Now, compute Y scale and normalize 2nd row.
+ scale[1] = row1.vectorLength();
+ row1.divide(scale[1]);
+ skew[0] /= scale[1];
+
+ // Compute XZ and YZ shears, orthogonalize 3rd row
+ skew[1] = row1.dot(row2);
+ row2.combine(row0, 1.0, -skew[1]);
+ skew[2] = row1.dot(row2);
+ row2.combine(row1, 1.0, -skew[2]);
+
+ // Next, get Z scale and normalize 3rd row.
+ scale[2] = row2.vectorLength();
+ row2.divide(scale[2]);
+ skew[1] /= scale[2];
+ skew[2] /= scale[2];
+
+ // At this point, the matrix (in rows) is orthonormal.
+ // Check for a coordinate system flip. If the determinant
+ // is -1, then negate the matrix and the scaling factors.
+ var pdum3 = new J3DIVector3(row1);
+ pdum3.cross(row2);
+ if (row0.dot(pdum3) < 0) {
+ for (i = 0; i < 3; i++) {
+ scale[i] *= -1;
+ row[0][i] *= -1;
+ row[1][i] *= -1;
+ row[2][i] *= -1;
+ }
+ }
+
+ // Now, get the rotations out
+ rotate[1] = Math.asin(-row0[2]);
+ if (Math.cos(rotate[1]) != 0) {
+ rotate[0] = Math.atan2(row1[2], row2[2]);
+ rotate[2] = Math.atan2(row0[1], row0[0]);
+ }
+ else {
+ rotate[0] = Math.atan2(-row2[0], row1[1]);
+ rotate[2] = 0;
+ }
+
+ // Convert rotations to degrees
+ var rad2deg = 180 / Math.PI;
+ rotate[0] *= rad2deg;
+ rotate[1] *= rad2deg;
+ rotate[2] *= rad2deg;
+
+ return true;
+}
+
+J3DIMatrix4.prototype._determinant2x2 = function(a, b, c, d)
+{
+ return a * d - b * c;
+}
+
+J3DIMatrix4.prototype._determinant3x3 = function(a1, a2, a3, b1, b2, b3, c1, c2, c3)
+{
+ return a1 * this._determinant2x2(b2, b3, c2, c3)
+ - b1 * this._determinant2x2(a2, a3, c2, c3)
+ + c1 * this._determinant2x2(a2, a3, b2, b3);
+}
+
+J3DIMatrix4.prototype._determinant4x4 = function()
+{
+ var a1 = this.$matrix.m11;
+ var b1 = this.$matrix.m12;
+ var c1 = this.$matrix.m13;
+ var d1 = this.$matrix.m14;
+
+ var a2 = this.$matrix.m21;
+ var b2 = this.$matrix.m22;
+ var c2 = this.$matrix.m23;
+ var d2 = this.$matrix.m24;
+
+ var a3 = this.$matrix.m31;
+ var b3 = this.$matrix.m32;
+ var c3 = this.$matrix.m33;
+ var d3 = this.$matrix.m34;
+
+ var a4 = this.$matrix.m41;
+ var b4 = this.$matrix.m42;
+ var c4 = this.$matrix.m43;
+ var d4 = this.$matrix.m44;
+
+ return a1 * this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
+ - b1 * this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
+ + c1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
+ - d1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
+}
+
+J3DIMatrix4.prototype._makeAdjoint = function()
+{
+ var a1 = this.$matrix.m11;
+ var b1 = this.$matrix.m12;
+ var c1 = this.$matrix.m13;
+ var d1 = this.$matrix.m14;
+
+ var a2 = this.$matrix.m21;
+ var b2 = this.$matrix.m22;
+ var c2 = this.$matrix.m23;
+ var d2 = this.$matrix.m24;
+
+ var a3 = this.$matrix.m31;
+ var b3 = this.$matrix.m32;
+ var c3 = this.$matrix.m33;
+ var d3 = this.$matrix.m34;
+
+ var a4 = this.$matrix.m41;
+ var b4 = this.$matrix.m42;
+ var c4 = this.$matrix.m43;
+ var d4 = this.$matrix.m44;
+
+ // Row column labeling reversed since we transpose rows & columns
+ this.$matrix.m11 = this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
+ this.$matrix.m21 = - this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
+ this.$matrix.m31 = this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
+ this.$matrix.m41 = - this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+ this.$matrix.m12 = - this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
+ this.$matrix.m22 = this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
+ this.$matrix.m32 = - this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
+ this.$matrix.m42 = this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
+
+ this.$matrix.m13 = this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
+ this.$matrix.m23 = - this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
+ this.$matrix.m33 = this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
+ this.$matrix.m43 = - this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
+
+ this.$matrix.m14 = - this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
+ this.$matrix.m24 = this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
+ this.$matrix.m34 = - this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
+ this.$matrix.m44 = this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
+}
+
+//
+// J3DIVector3
+//
+J3DIVector3 = function(x,y,z)
+{
+ this.load(x,y,z);
+}
+
+J3DIVector3.prototype.load = function(x,y,z)
+{
+ if (typeof x == 'object' && "length" in x) {
+ this[0] = x[0];
+ this[1] = x[1];
+ this[2] = x[2];
+ }
+ else if (typeof x == 'number') {
+ this[0] = x;
+ this[1] = y;
+ this[2] = z;
+ }
+ else {
+ this[0] = 0;
+ this[1] = 0;
+ this[2] = 0;
+ }
+}
+
+J3DIVector3.prototype.getAsArray = function()
+{
+ return [ this[0], this[1], this[2] ];
+}
+
+J3DIVector3.prototype.getAsFloat32Array = function()
+{
+ return new Float32Array(this.getAsArray());
+}
+
+J3DIVector3.prototype.vectorLength = function()
+{
+ return Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2]);
+}
+
+J3DIVector3.prototype.divide = function(divisor)
+{
+ this[0] /= divisor; this[1] /= divisor; this[2] /= divisor;
+}
+
+J3DIVector3.prototype.cross = function(v)
+{
+ this[0] = this[1] * v[2] - this[2] * v[1];
+ this[1] = -this[0] * v[2] + this[2] * v[0];
+ this[2] = this[0] * v[1] - this[1] * v[0];
+}
+
+J3DIVector3.prototype.dot = function(v)
+{
+ return this[0] * v[0] + this[1] * v[1] + this[2] * v[2];
+}
+
+J3DIVector3.prototype.combine = function(v, ascl, bscl)
+{
+ this[0] = (ascl * this[0]) + (bscl * v[0]);
+ this[1] = (ascl * this[1]) + (bscl * v[1]);
+ this[2] = (ascl * this[2]) + (bscl * v[2]);
+}
+
+J3DIVector3.prototype.multVecMatrix = function(matrix)
+{
+ var x = this[0];
+ var y = this[1];
+ var z = this[2];
+
+ this[0] = matrix.$matrix.m41 + x * matrix.$matrix.m11 + y * matrix.$matrix.m21 + z * matrix.$matrix.m31;
+ this[1] = matrix.$matrix.m42 + x * matrix.$matrix.m12 + y * matrix.$matrix.m22 + z * matrix.$matrix.m32;
+ this[2] = matrix.$matrix.m43 + x * matrix.$matrix.m13 + y * matrix.$matrix.m23 + z * matrix.$matrix.m33;
+ var w = matrix.$matrix.m44 + x * matrix.$matrix.m14 + y * matrix.$matrix.m24 + z * matrix.$matrix.m34;
+ if (w != 1 && w != 0) {
+ this[0] /= w;
+ this[1] /= w;
+ this[2] /= w;
+ }
+}
+
+J3DIVector3.prototype.toString = function()
+{
+ return "["+this[0]+","+this[1]+","+this[2]+"]";
+}
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list