Mercurial > hg > Members > e085711
changeset 26:933062d8e917
update library J3DI.js J3DMath.js
author | NOBUYASU Oshiro |
---|---|
date | Tue, 09 Nov 2010 00:03:42 +0900 |
parents | e8c591a01a8e |
children | e3a50cb29c85 |
files | webGL/dandy/dandy.html webGL/dandy/resources/J3DI.js webGL/dandy/resources/J3DI.js.old webGL/dandy/resources/J3DI.js~ webGL/dandy/resources/J3DIMath.js.old webGL/dandy/resources/parse.js~ |
diffstat | 6 files changed, 2447 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webGL/dandy/dandy.html Tue Nov 09 00:03:42 2010 +0900 @@ -0,0 +1,206 @@ +<!DOCTYPE html> + +<html> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <title>WebGL dandy</title> + <script src="resources/J3DI.js"> </script> + <script src="resources/J3DIMath.js"> </script> + <script src="resources/jkl-parsexml.js"> </script> + <script src="resources/makePanel.js"> </script> + <script src="resources/Character_state.js"> </script> + <script src="resources/Character.js"> </script> + <script src="resources/schedule.js"> </script> + <script src="resources/Player.js"> </script> + <script src="resources/enemy.js"> </script> + <script src="resources/bullet.js"> </script> + <script src="resources/collision.js"> </script> + <script src="resources/constKey.js"> </script> + <script src="resources/keybord.js"> </script> + <script src="resources/boss.js"> </script> + <script src="resources/parse.js"> </script> + <script src="resources/bom.js"> </script> + <script src="resources/pause.js"> </script> + <script src="resources/tama.js"> </script> + <script src="resources/sankaku.js"> </script> + <script src="resources/syokika.js"> </script> + <script src="resources/sound.js"> </script> + <script src="resources/const.js"> </script> + <script src="resources/charaTable.js"> </script> + + <script id="vshader" type="x-shader/x-vertex"> + uniform mat4 u_modelViewProjMatrix; + uniform mat4 u_normalMatrix; + uniform vec3 lightDir; + + attribute vec3 vNormal; + attribute vec4 vTexCoord; + attribute vec4 vPosition; + + varying float v_Dot; + varying vec2 v_texCoord; + + void main() + { + gl_Position = u_modelViewProjMatrix * vPosition; + v_texCoord = vTexCoord.st; + vec4 transNormal = u_normalMatrix * vec4(vNormal,1); + v_Dot = max(dot(transNormal.xyz, lightDir), 0.0); + } + </script> + + + <script id="fshader" type="x-shader/x-fragment"> +#ifdef GL_ES + precision mediump float; +#endif + + uniform sampler2D sampler2d; + + varying float v_Dot; + varying vec2 v_texCoord; + + void main() + { + vec4 color = texture2D(sampler2d,v_texCoord); + // color += vec4(0.1,0.1,0.1,1); + // if(color.a == 1)color=vec4(1,0,0,1); + // else color=vec4(0,1,1,1); + gl_FragColor = vec4(color.xyz * v_Dot, color.a); + // gl_FragColor = vec4(color.xyz * v_Dot, 0.5); + } + </script> + + <script> + + //画面(canvas)の大きさ + var w = 1024; + var h = 640; + function init() + { + var gl = initWebGL("example", "vshader", "fshader", + [ "vNormal", "vTexCoord", "vPosition"], + [ 0, 0, 0, 1 ], 10000); + + gl.uniform3f(gl.getUniformLocation(gl.program, "lightDir"), 0, 0, 1); + gl.uniform1i(gl.getUniformLocation(gl.program, "sampler2d"), 0); + + gl.enable(gl.TEXTURE_2D); + + sankakuf();//mycos,mysinの作成 sankaku.js + parseXml(gl);//parse.js + initEnemyTable(gl);//parseXmlの後に呼ぶこと + + return gl; + } + + width = -1; + height = -1; + + function reshape(ctx, ortho) + { + var canvas = document.getElementById('example'); + if (canvas.width == width && canvas.width == height) + return; + + + width = canvas.width; + height = canvas.height; + + ctx.viewport(0, 0, width, height); + + ctx.perspectiveMatrix = new J3DIMatrix4(); +// ctx.perspectiveMatrix.ortho(50, -150, 0, -140, -1000, 10000); + ctx.perspectiveMatrix.ortho(ortho.left, -ortho.right, ortho.top, -ortho.bottom, 0, 10000); + +// ctx.perspectiveMatrix.perspective(30, width/height, 1, 10000); + } + + + + function loop(ctx, ortho) + { + reshape(ctx, ortho); + ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); + + Player(ctx, jiki, pad, ortho); + + obj_draw(ctx); + + PutBom(ctx); + pause(); + + + ctx.flush(); + + filpcount++; + schedule(); + + state_update(); + + collision_detect(); + delete_obj( ctx ) + + framerate.snapshot(); + } + + function opening(ctx, ortho) + { + reshape(ctx, ortho); + ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); + + PutSpriteF(ctx, 100, 70, 1, font[10]); + PutSpriteF(ctx, 170, 50, 1, font[11]); + PutSpriteF(ctx, 40, 120, 1, font[12]); + + ctx.flush(); + + if(pad.start == 0) {setTimeout(o, 100);} + if(pad.start != 0) { + jiki.bf = true; + pad.st = 1; + gameflage = 1; + SoundPlay(0); + setInterval(f, 10); + } + } + function start() + { + var ortho = makeOrthoPara(0,200,140,0); + + var c = document.getElementById("example"); + + + //画面の大きさ + c.width = w; + c.height = h; + + var ctx = init(); + + + currentAngle = 0; + incAngle = 10; + f = function() { loop(ctx, ortho) }; + o = function() {opening(ctx, ortho)} + setTimeout(o, 10); + framerate = new Framerate("framerate"); + } + </script> + <style type="text/css"> + canvas { + border: 2px solid black; + } + </style> + </head> + <body onload="start()" onkeydown="keybordDown()" onkeypress="keybordPress()" onkeyup="keybordUp()" style='overflow:hidden'> + <!--<body onload = "start()" style='overflow:hidden'> --> + <canvas id="example"> + There is supposed to be an example drawing here, but it's not important. + </canvas> + <div id="framerate"></div> + <div id="console"></div> + + <img id="test" style="border:1px solid red"> + + </body> +</html>
--- a/webGL/dandy/resources/J3DI.js Fri Nov 05 08:40:26 2010 +0900 +++ b/webGL/dandy/resources/J3DI.js Tue Nov 09 00:03:42 2010 +0900 @@ -72,7 +72,7 @@ gl.attachShader (gl.program, fragmentShader); // Bind attributes - for (var i in attribs) + for (var i = 0; i < attribs.length; ++i) gl.bindAttribLocation (gl.program, i, attribs[i]); // Link the program @@ -97,7 +97,7 @@ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); gl.clearDepth(clearDepth); -// gl.enable(gl.DEPTH_TEST); + // gl.enable(gl.DEPTH_TEST); gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webGL/dandy/resources/J3DI.js.old Tue Nov 09 00:03:42 2010 +0900 @@ -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; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webGL/dandy/resources/J3DI.js~ Tue Nov 09 00:03:42 2010 +0900 @@ -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 = 0; i < attribs.length; ++i) + 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; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webGL/dandy/resources/J3DIMath.js.old Tue Nov 09 00:03:42 2010 +0900 @@ -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]+"]"; +} \ No newline at end of file
--- a/webGL/dandy/resources/parse.js~ Fri Nov 05 08:40:26 2010 +0900 +++ b/webGL/dandy/resources/parse.js~ Tue Nov 09 00:03:42 2010 +0900 @@ -189,13 +189,14 @@ ctx.bindBuffer(ctx.ARRAY_BUFFER, glObj.texCoordObject); ctx.vertexAttribPointer(1, 2, ctx.FLOAT, false, 0, 0); - + ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, glObj.indexObject); + // generate the model-view matrix var mvMatrix = new J3DIMatrix4(); - mvMatrix.translate( x, y, 1); mvMatrix.scale(scale, scale, scale); + mvMatrix.translate( x, y, 10); // construct the normal matrix from the model-view matrix var normalMatrix = new J3DIMatrix4(mvMatrix); @@ -206,7 +207,7 @@ // construct the model-view * projection matrix var mvpMatrix = new J3DIMatrix4(ctx.perspectiveMatrix); mvpMatrix.multiply(mvMatrix); - mvpMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false); + mvpMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false); ctx.bindTexture(ctx.TEXTURE_2D, glObj.texture); @@ -215,7 +216,7 @@ } -function PutSpriteLock(ctx, x, y, scale, angle, glObj) +function PutSpriteA(ctx, x, y, scale, angle, glObj) { // setup VBOs @@ -236,20 +237,18 @@ // generate the model-view matrix var mvMatrix = new J3DIMatrix4(); mvMatrix.scale(scale, scale, scale); + mvMatrix.translate( x, y, 10); mvMatrix.rotate(angle, 0, 0, 1); - mvMatrix.translate( x, y, 10); // construct the normal matrix from the model-view matrix var normalMatrix = new J3DIMatrix4(mvMatrix); normalMatrix.invert(); normalMatrix.transpose(); -// ctx.uniformMatrix4fv(ctx.getUniformLocation(ctx.program, "u_normalMatrix"), false, normalMatrix.getAsFloat32Array()); normalMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_normalMatrix"), false); // construct the model-view * projection matrix - var mvpMatrix = new J3DIMatrix4(mvMatrix); - mvpMatrix.multiply(ctx.perspectiveMatrix); -// ctx.uniformMatrix4fv(ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false, mvpMatrix.getAsFloat32Array()); + var mvpMatrix = new J3DIMatrix4(ctx.perspectiveMatrix); + mvpMatrix.multiply(mvMatrix); mvpMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false);