Index: ../trunk-jpl/src/m/plot/plot_quiver.js =================================================================== --- ../trunk-jpl/src/m/plot/plot_quiver.js (revision 21093) +++ ../trunk-jpl/src/m/plot/plot_quiver.js (revision 21094) @@ -10,7 +10,6 @@ var vertices = []; var indices = []; var colors = []; - var rgbcolor = []; var xmin,xmax; var ymin,ymax; var zmin,zmax; @@ -65,7 +64,7 @@ canvas.nodes[canvas.nodes.length] = node; scale = 1 / (xmax - xmin); node["shaderName"] = "colored"; - node["shader"] = gl["shaders"][node["shaderName"]]["program"]; + node["shader"] = gl["shaders"][node["shaderName"]]; node["lineWidth"] = options.getfieldvalue('linewidth',1); node["scale"] = [scale, scale, scale * matrixscale]; node["translation"] = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (2 / scale)]; @@ -76,9 +75,6 @@ node["maskEnabled"] = options.getfieldvalue('innermask','off') == 'on'; node["maskHeight"] = options.getfieldvalue('innermaskheight',150.0)*options.getfieldvalue('heightscale',1); node["maskColor"] = options.getfieldvalue('innermaskcolor',[0.0,0.0,1.0,1.0]); - - //some defaults: - colors.itemSize = 4; //retrieve some options var edgecolor=new RGBColor(options.getfieldvalue('edgecolor','black')); @@ -91,7 +87,6 @@ else if (elements[0].length==4){ //tetras } else{ //2D triangular elements - vertices.itemSize = 3; var xyz = vec3.create(); var xyz = vec3.create(); var direction = vec3.create(); @@ -136,8 +131,5 @@ } } //}}} - - /*Initalize buffers: */ - node["arrays"] = [vertices, colors]; - node["buffers"] = initBuffers(gl, node["arrays"]); + node["mesh"] = GL.Mesh.load({vertices:vertices, colors:colors}); } Index: ../trunk-jpl/src/m/plot/plot_overlay.js =================================================================== --- ../trunk-jpl/src/m/plot/plot_overlay.js (revision 21093) +++ ../trunk-jpl/src/m/plot/plot_overlay.js (revision 21094) @@ -62,7 +62,7 @@ canvas.nodes[canvas.nodes.length] = node; scale = 1 / (xmax - xmin); node["shaderName"] = "unlit_textured"; - node["shader"] = gl["shaders"][node["shaderName"]]["program"]; + node["shader"] = gl["shaders"][node["shaderName"]]; node["scale"] = [scale, scale, scale * matrixscale]; node["translation"] = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (2 / scale)]; node["modelMatrix"] = recalculateModelMatrix(node); @@ -72,10 +72,6 @@ node["maskEnabled"] = options.getfieldvalue('outermask','off') == 'on'; node["maskHeight"] = options.getfieldvalue('outermaskheight',150.0); node["maskColor"] = options.getfieldvalue('outermaskcolor',[0.0,0.0,1.0,1.0]); - - //some defaults: - texcoords.itemSize = 2; - vertices.itemSize = 3; //Handle outer radaroverlay if (md.radaroverlay.outerx) { @@ -151,7 +147,6 @@ texcoords[texcoords.length] = (y[i] - modelylim[0]) / yrange; } } - //linearize the elements array: var element; for(var i = 0; i < elements.length; i++){ @@ -161,9 +156,5 @@ indices[indices.length] = element[1]; indices[indices.length] = element[2]; } - indices.itemSize = 1; - - /*Initalize buffers: */ - node["arrays"] = [vertices, texcoords, indices]; - node["buffers"] = initBuffers(gl,node["arrays"]); + node["mesh"] = GL.Mesh.load({vertices:vertices, coords:texcoords, indices:indices}); } Index: ../trunk-jpl/src/m/plot/plot_mesh.js =================================================================== --- ../trunk-jpl/src/m/plot/plot_mesh.js (revision 21093) +++ ../trunk-jpl/src/m/plot/plot_mesh.js (revision 21094) @@ -62,7 +62,7 @@ canvas.nodes[canvas.nodes.length] = node; scale = 1 / (xmax - xmin); node["shaderName"] = "colored"; - node["shader"] = gl["shaders"][node["shaderName"]]["program"]; + node["shader"] = gl["shaders"][node["shaderName"]]; node["lineWidth"] = options.getfieldvalue('linewidth',1); node["scale"] = [scale, scale, scale * matrixscale]; node["translation"] = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (2 / scale)]; @@ -72,9 +72,6 @@ node["maskEnabled"] = options.getfieldvalue('innermask','off') == 'on'; node["maskHeight"] = options.getfieldvalue('innermaskheight',150.0)*options.getfieldvalue('heightscale',1); node["maskColor"] = options.getfieldvalue('innermaskcolor',[0.0,0.0,1.0,1.0]); - - //some defaults: - colors.itemSize = 4; //retrieve some options var edgecolor = new RGBColor(options.getfieldvalue('edgecolor','black')); @@ -87,7 +84,6 @@ else if (elements[0].length==4){ //tetras } else{ //2D triangular elements - vertices.itemSize = 3; var xyz = vec3.create(); var direction = vec3.create(); var vertex = vec3.create(); @@ -134,11 +130,7 @@ indices[indices.length] = element[2]; indices[indices.length] = element[0]; } - indices.itemSize = 1; } //}}} - - /*Initalize buffers: */ - node["arrays"] = [vertices, colors, indices]; - node["buffers"] = initBuffers(gl, node["arrays"]); + node["mesh"] = GL.Mesh.load({vertices:vertices, colors:colors, indices:indices}); } Index: ../trunk-jpl/src/m/plot/webgl.js =================================================================== --- ../trunk-jpl/src/m/plot/webgl.js (revision 21093) +++ ../trunk-jpl/src/m/plot/webgl.js (revision 21094) @@ -14,18 +14,15 @@ } function initWebGL(canvas,options) { //{{{ var gl; - try { - // Try to grab the standard context. If it fails, fallback to experimental. - gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); + if (!canvas.gl) gl = GL.create({canvas:canvas}); + else gl = canvas.gl; } - catch(e) {} - - // If we don't have a GL context, give up now - if (!gl) { - alert("Unable to initialize WebGL. Your browser may not support it."); + catch(e) { + console.log(e); + return; } - + // Enable depth testing gl.enable(gl.DEPTH_TEST); // Near things obscure far things @@ -33,10 +30,6 @@ // Enable color blending/overlay gl.enable(gl.BLEND); - // Allocate arrays equal to maximium number of attributes used by any one shader - gl.enableVertexAttribArray(0); - gl.enableVertexAttribArray(1); - // Load shaders and store them in gl object gl.shaders = loadShaders(gl); @@ -79,52 +72,13 @@ return gl; } //}}} -function initBuffers(gl,arrays) { //{{{ - var bufferArray = []; - for (var i = 0; i < arrays.length; i++) { - bufferArray[i] = gl.createBuffer(); - bufferArray[i].itemSize = arrays[i].itemSize; - bufferArray[i].numItems = arrays[i].length/bufferArray[i].itemSize; - - if (bufferArray[i].itemSize > 1) { - gl.bindBuffer(gl.ARRAY_BUFFER, bufferArray[i]); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrays[i]), gl.STATIC_DRAW); - } - else { - //TODO: identify index buffers uniquely (by name) - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferArray[i]); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(arrays[i]), gl.STATIC_DRAW); - } - } - return bufferArray; -} //}}} function initTexture(gl,imageSource) { //{{{ - var texture = gl.createTexture(); - texture.image = new Image(); - texture.isLoaded = false; - texture.image.onload = function () { - handleLoadedTexture(gl,texture); - } - texture.image.src = imageSource; - return texture; + return GL.Texture.fromURL(imageSource, {minFilter:gl.LINEAR_MIPMAP_LINEAR, magFilter:gl.LINEAR}); } //}}} -function handleLoadedTexture(gl,texture) { //{{{ - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); - gl.generateMipmap(gl.TEXTURE_2D); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.bindTexture(gl.TEXTURE_2D, null); - texture.isLoaded = true; -} //}}} function Node(gl,options) { //{{{ //Returns a Node object that contains default display states for webgl object return {buffers:[], - shader:gl.shaders["colored"]["program"], + shader:gl.shaders["colored"], draw:null, hideOcean:false, level:0, @@ -194,137 +148,89 @@ var shaderNames = ["colored", "unlit_textured"]; shaders = {}; shaders["colored"] = {loaded:false, vsh:{}, fsh:{}}; - shaders["colored"]["vsh"]["string"] = - ['attribute vec3 aVertexPosition;', - 'attribute vec4 aVertexColor;', - '', - 'uniform mat4 uMVPMatrix;', - 'uniform float uAlpha;', - '', - 'varying vec4 vColor;', - '', - 'void main(void) {', - ' gl_PointSize = 3.0;', - ' gl_Position = uMVPMatrix * vec4(aVertexPosition.xyz, 1.0);', - ' vColor = vec4(aVertexColor.xyz, uAlpha);', - '}'].join('\n'); - shaders["colored"]["fsh"]["string"] = - ['precision mediump float;', - '', - 'varying vec4 vColor;', - '', - 'void main(void) {', - ' gl_FragColor = vColor;', - '}'].join('\n'); - shaders["unlit_textured"] = {loaded:false, vsh:{}, fsh:{}}; - shaders["unlit_textured"]["vsh"]["string"] = - ['attribute vec3 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - '', - 'uniform mat4 uMVPMatrix;', - '', - 'varying vec2 vTextureCoord;', - 'varying float vZCoord;', - '', - 'void main(void) {', - ' gl_PointSize = 3.0;', - ' gl_Position = uMVPMatrix * vec4(aVertexPosition.xyz, 1.0);', - ' vTextureCoord = aTextureCoord;', - ' vZCoord = aVertexPosition.z;', - '}'].join('\n'); - shaders["unlit_textured"]["fsh"]["string"] = - ['precision mediump float;', - '', - 'varying vec2 vTextureCoord;', - 'varying float vZCoord;', - '', - 'uniform sampler2D uColorSampler;', - 'uniform float uAlpha;', - 'uniform bool uMaskEnabled;', - 'uniform float uMaskHeight;', - 'uniform vec4 uMaskColor;', - '', - 'void main(void) {', - ' if (uMaskEnabled && (vZCoord < uMaskHeight)) {', - ' gl_FragColor = vec4(uMaskColor.xyz, uAlpha);', - ' }', - ' else {', - ' gl_FragColor = vec4(texture2D(uColorSampler, vec2(vTextureCoord.s, vTextureCoord.t)).rgb, uAlpha);', - ' }', - '}'].join('\n'); - shaderNames.forEach(function(shaderName){ - shaders[shaderName]["vsh"]["shader"] = getShaderByString(gl, shaders[shaderName]["vsh"]["string"], "vsh"); - shaders[shaderName]["fsh"]["shader"] = getShaderByString(gl, shaders[shaderName]["fsh"]["string"], "fsh"); - - shaders[shaderName]["program"] = gl.createProgram(); - gl.attachShader(shaders[shaderName]["program"], shaders[shaderName]["vsh"]["shader"]); - gl.attachShader(shaders[shaderName]["program"], shaders[shaderName]["fsh"]["shader"]); - gl.linkProgram(shaders[shaderName]["program"]); - - if (!gl.getProgramParameter(shaders[shaderName]["program"], gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - var vshStringArray = shaders[shaderName]["vsh"]["string"].split("\n"); - var fshStringArray = shaders[shaderName]["fsh"]["string"].split("\n"); - var line = ""; - var property = ""; - for (var i = 0; i < vshStringArray.length; i++) { - line = vshStringArray[i]; - if (line.search("attribute") != -1) { - property = nameFromLine(line); - shaders[shaderName]["program"][property] = gl.getAttribLocation(shaders[shaderName]["program"], property); - } - else if (line.search("uniform") != -1) { - property = nameFromLine(line); - shaders[shaderName]["program"][property] = gl.getUniformLocation(shaders[shaderName]["program"], property); - } - else if (line.search("void main") != -1) { - break; - } - } - for (var i = 0; i < fshStringArray.length; i++) { - line = fshStringArray[i]; - if (line.search("uniform") != -1) { - property = nameFromLine(line); - shaders[shaderName]["program"][property] = gl.getUniformLocation(shaders[shaderName]["program"], property); - } - else if (line.search("void main") != -1) { - break; - } - } - shaders[shaderName]["loaded"] = true; - }); + //basic phong shader + shaders["colored"] = new Shader('\ + precision highp float;\ + attribute vec3 a_vertex;\ + attribute vec4 a_color;\ + uniform mat4 u_mvp;\ + uniform float u_alpha;\ + varying vec4 v_color;\ + void main() {\ + gl_PointSize = 3.0;\ + gl_Position = u_mvp * vec4(a_vertex.xyz, 1.0);\ + v_color = vec4(a_color.xyz, u_alpha);\ + }\ + ', '\ + precision mediump float;\ + varying vec4 v_color;\ + void main() {\ + gl_FragColor = v_color;\ + }\ + '); + + shaders["unlit_textured"] = new Shader('\ + precision highp float;\ + attribute vec3 a_vertex;\ + attribute vec2 a_coord;\ + uniform mat4 u_mvp;\ + varying vec2 v_coord;\ + varying float v_z;\ + void main() {\ + gl_PointSize = 3.0;\ + gl_Position = u_mvp * vec4(a_vertex.xyz, 1.0);\ + v_coord = a_coord;\ + v_z = a_vertex.z;\ + }\ + ', '\ + precision mediump float;\ + varying vec2 v_coord;\ + varying float v_z;\ + uniform sampler2D u_texture;\ + uniform float u_alpha;\ + uniform bool u_maskEnabled;\ + uniform float u_maskHeight;\ + uniform vec4 u_maskColor;\ + void main() {\ + if (u_maskEnabled && (v_z < u_maskHeight)) {\ + gl_FragColor = vec4(u_maskColor.rgb, u_alpha);\ + }\ + else {\ + gl_FragColor = vec4(texture2D(u_texture, v_coord).rgb, u_alpha);\ + }\ + }\ + '); + /* + shaders["phong"] = new Shader('\ + precision highp float;\ + attribute vec3 a_vertex;\ + attribute vec3 a_normal;\ + attribute vec2 a_coord;\ + varying vec3 v_normal;\ + varying vec2 v_coord;\ + uniform mat4 u_mvp;\ + uniform mat4 u_model;\ + void main() {\ + v_coord = a_coord;\ + v_normal = (u_model * vec4(a_normal,0.0)).xyz;\ + gl_Position = u_mvp * vec4(a_vertex,1.0);\ + }\ + ', '\ + precision highp float;\ + varying vec3 v_normal;\ + varying vec2 v_coord;\ + uniform vec3 u_lightvector;\ + uniform vec4 u_color;\ + uniform sampler2D u_texture;\ + void main() {\ + vec3 N = normalize(v_normal);\ + vec4 color = u_color * texture2D( u_texture, v_coord);\ + gl_FragColor = color * max(0.0, dot(u_lightvector,N));\ + }\ + '); + */ return shaders; } //}}} -function getShaderByString(gl,str,type) { //{{{ - var shader; - if (type == "fsh") { - shader = gl.createShader(gl.FRAGMENT_SHADER); - } - else if (type == "vsh") { - shader = gl.createShader(gl.VERTEX_SHADER); - } - else { - return null; - } - - gl.shaderSource(shader, str); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} //}}} -function nameFromLine(line) { //{{{ - //returns lowerCamelCase property name from shader line - var fullName = line.split(" ")[2]; - return fullName.slice(0, fullName.search(";")); -} //}}} -//}}} //{{{ Interface Functions function onPan(ev,canvas,displaylog) { //{{{ ev.preventDefault(); @@ -427,60 +333,31 @@ mat4.multiply(canvas.cameraMatrix, pMatrix, vMatrix); }//}}} function drawSceneGraphNode(canvas,node) { //{{{ - if (!node["enabled"]) { - return; - } - if (node["texture"]) { - if (!node["texture"]["isLoaded"]) { - return; - } - } - var gl = canvas.gl; - bindAttributes(gl, node["shader"], node["buffers"]); + if (!node["enabled"]) return; + var mvpMatrix = mat4.create(); mat4.multiply(mvpMatrix, canvas.cameraMatrix, node["modelMatrix"]); - gl.uniformMatrix4fv(node["shader"]["uMVPMatrix"], false, mvpMatrix); - gl.uniform1f(node["shader"]["uAlpha"], node["alpha"]); - gl.uniform1i(node["shader"]["uMaskEnabled"], node["maskEnabled"]); - gl.uniform1f(node["shader"]["uMaskHeight"], node["maskHeight"]); - gl.uniform4fv(node["shader"]["uMaskColor"], node["maskColor"]); - if (node["texture"]) { - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, node["texture"]); - gl.uniform1i(node["shader"]["uColorSampler"], 0); - } - if (node["disableDepthTest"]) { - gl.disable(gl.DEPTH_TEST); - } + + if (node["texture"]) node["texture"].bind(0); + if (node["disableDepthTest"]) gl.disable(gl.DEPTH_TEST); + gl.lineWidth(node["lineWidth"]); - gl.blendFunc (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - if (node["useIndexBuffer"] == true) { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, node["buffers"][node["buffers"].length - 1]); - gl.drawElements(node["drawMode"], node["buffers"][node["buffers"].length - 1].numItems, gl.UNSIGNED_SHORT, 0); - } - else { - gl.drawArrays(node["drawMode"], 0, node["buffers"][0].numItems); - } + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + + node["shader"].uniforms({ + u_mvp: mvpMatrix, + u_texture: 0, + u_alpha: node["alpha"], + u_maskEnabled: node["maskEnabled"], + u_maskHeight: node["maskHeight"], + u_maskColor: node["maskColor"] + }) + if (node["useIndexBuffer"] == true) node["shader"].draw(node["mesh"], node["drawMode"], "indices"); + else node["shader"].draw(node["mesh"], node["drawMode"]); + gl.enable(gl.DEPTH_TEST); } //}}} -function bindAttributes(gl,shaderProgram,bufferArray) { //{{{ - gl.useProgram(shaderProgram); - var arrayNumber = 0; - for (var propertyName in shaderProgram) { - if (propertyName[0] == "a") { - if (bufferArray[arrayNumber].itemSize > 1) { - gl.bindBuffer(gl.ARRAY_BUFFER, bufferArray[arrayNumber]); - gl.vertexAttribPointer(shaderProgram[propertyName], bufferArray[arrayNumber].itemSize, gl.FLOAT, false, 0, 0); - arrayNumber++; - } - } - } -} //}}} function draw(canvas,options) { //{{{ - if (canvas.nodes.length < 1) { - canvas.drawHandler = window.requestAnimationFrame(function(time) {draw(canvas,options)}); - return; - } // Ensure canvas and gl viewport sizes are the same var displayWidth = canvas.clientWidth; var displayHeight = canvas.clientHeight; @@ -492,20 +369,24 @@ if (canvas.textcanvas) canvas.textcanvas.draw(canvas); - var gl = canvas.gl; - gl.clearColor(canvas.backgroundcolor[0], canvas.backgroundcolor[1], canvas.backgroundcolor[2], canvas.backgroundcolor[3]); - - // Skip drawing of new frame if any texture is not yet loaded var nodes = canvas.nodes; + if (nodes.length < 1) { + canvas.drawHandler = window.requestAnimationFrame(function(time) {draw(canvas,options)}); + return; + } for (var node in nodes) { - if (nodes[node]["texture"] && !nodes[node]["texture"]["isLoaded"]) { + if (nodes[node]["texture"] && nodes[node]["texture"]["ready"] == false) { canvas.drawHandler = window.requestAnimationFrame(function(time) {draw(canvas,options)}); return; } } - // Else, clear the color as well as the depth buffer for new frame + + var gl = canvas.gl; + gl.clearColor(canvas.backgroundcolor[0], canvas.backgroundcolor[1], canvas.backgroundcolor[2], canvas.backgroundcolor[3]); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + updateCameraMatrix(canvas); var drawPassNumber = 2; Index: ../trunk-jpl/src/m/plot/plot_unit.js =================================================================== --- ../trunk-jpl/src/m/plot/plot_unit.js (revision 21093) +++ ../trunk-jpl/src/m/plot/plot_unit.js (revision 21094) @@ -7,16 +7,6 @@ // See also: PLOTMODEL, PLOT_MANAGER //declare variables: {{{ - var vertices = []; - var indices = []; - var texcoords = []; - var nanindices = {}; - var xmin,xmax; - var ymin,ymax; - var zmin,zmax; - var datamin,datamax,datadelta; - var scale,matrixscale,vertexscale; - //Process data and model var meshresults = processmesh(md,data,options); var x = meshresults[0]; @@ -25,6 +15,16 @@ var elements = meshresults[3]; var is2d = meshresults[4]; var isplanet = meshresults[5]; + + var vertices = new Float32Array(x.length * 3); + var texcoords = new Float32Array(x.length * 2); + var indices = new Uint16Array(elements.length * 3); + var nanindices = {}; + var xmin,xmax; + var ymin,ymax; + var zmin,zmax; + var datamin,datamax,datadelta; + var scale,matrixscale,vertexscale; //Compue scaling through matrices for 2d meshes and vertices for 3d meshes if (!md.geometry.surface) { @@ -64,7 +64,7 @@ canvas.nodes[canvas.nodes.length] = node; scale = 1 / (xmax - xmin); node["shaderName"] = "unlit_textured"; - node["shader"] = gl["shaders"][node["shaderName"]]["program"]; + node["shader"] = gl["shaders"][node["shaderName"]]; node["scale"] = [scale, scale, scale * matrixscale]; node["translation"] = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (2 / scale)]; node["modelMatrix"] = recalculateModelMatrix(node); @@ -100,24 +100,21 @@ datamax = caxis[1]; datadelta = datamax - datamin; - vertices.itemSize = 3; - texcoords.itemSize = 2; - var xyz = vec3.create(); var direction = vec3.create(); var vertex = vec3.create(); var magnitude; - for(var i = 0; i < x.length; i++){ + for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){ //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i])) { nanindices[i] = i; - vertices[vertices.length] = vertex[0]; - vertices[vertices.length] = vertex[1]; - vertices[vertices.length] = vertex[2]; + vertices[vindex++] = vertex[0]; + vertices[vindex++] = vertex[1]; + vertices[vindex++] = vertex[2]; - texcoords[texcoords.length] = 0.0; - texcoords[texcoords.length] = 0.0; + texcoords[tindex++] = 0.0; + texcoords[tindex++] = 0.0; continue; } //Scale vertices @@ -125,30 +122,25 @@ magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; vec3.normalize(direction, xyz); vec3.scale(vertex, direction, magnitude); - vertices[vertices.length] = vertex[0]; - vertices[vertices.length] = vertex[1]; - vertices[vertices.length] = vertex[2]; + vertices[vindex++] = vertex[0]; + vertices[vindex++] = vertex[1]; + vertices[vindex++] = vertex[2]; - texcoords[texcoords.length] = 0.5; - texcoords[texcoords.length] = (data[i] - datamin) / datadelta; + texcoords[tindex++] = 0.5; + texcoords[tindex++] = (data[i] - datamin) / datadelta; } //linearize the elements array: var element; - for(var i = 0; i < elements.length; i++){ + for(var i = 0, iindex = 0; i < elements.length; i++){ element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; - indices[indices.length] = element[0]; - indices[indices.length] = element[1]; - indices[indices.length] = element[2]; + indices[iindex++] = element[0]; + indices[iindex++] = element[1]; + indices[iindex++] = element[2]; } - indices.itemSize = 1; - } - - //Initalize buffers - node["arrays"] = [vertices, texcoords, indices]; - node["buffers"] = initBuffers(gl,node["arrays"]); + node["mesh"] = GL.Mesh.load({vertices:vertices, coords:texcoords, indices:indices}); break; //}}} //quiver plot {{{ @@ -168,33 +160,26 @@ else if (elements[0].length==4){//tetras } else{ //triangular elements - vertices.itemSize = 3; - var xyz = vec3.create(); var direction = vec3.create(); var vertex = vec3.create(); var magnitude; var timestamps = data[data.length-1]; - for(var i = 0; i < x.length; i++){ + for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){ //Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i][0])) { nanindices[i] = i; - vertices[vertices.length] = vertex[0]; - vertices[vertices.length] = vertex[1]; - vertices[vertices.length] = vertex[2]; - - texcoords[texcoords.length] = 0.0; - texcoords[texcoords.length] = 0.0; - continue; } - //Scale vertices - xyz = vec3.fromValues(x[i], y[i], z[i]); - magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; - vec3.normalize(direction, xyz); - vec3.scale(vertex, direction, magnitude); - vertices[vertices.length] = vertex[0]; - vertices[vertices.length] = vertex[1]; - vertices[vertices.length] = vertex[2]; + else { + //Scale vertices + xyz = vec3.fromValues(x[i], y[i], z[i]); + magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale; + vec3.normalize(direction, xyz); + vec3.scale(vertex, direction, magnitude); + } + vertices[vindex++] = vertex[0]; + vertices[vindex++] = vertex[1]; + vertices[vindex++] = vertex[2]; } //Transpose data to obtain column addressable data matrix data = data[0].map(function(col, i) { @@ -203,65 +188,54 @@ }) }); //Prevent evaluation of datasubarray min/max if caxis exists - if (options.exist('caxis')) { - caxis = options.getfieldvalue('caxis'); - } - else { - caxis = [ArrayMin(data[0]),ArrayMax(data[0].slice(0,-1))]; - } + if (options.exist('caxis')) caxis = options.getfieldvalue('caxis'); + else caxis = [ArrayMin(data[0]),ArrayMax(data[0].slice(0,-1))]; if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log',10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))]; - + //Prepare texcoords to hold array of data values + texcoords = []; for(var i = 0; i < data.length; i++){ datamin = caxis[0]; datamax = caxis[1]; datadelta = datamax - datamin; - //Precalculate arrays for each datasubarray, trimming off timestamp value by using x.length instead of data[i].length - texcoords[i] = []; - texcoords[i].itemSize = 2; - for(var j = 0; j < x.length; j++){ - texcoords[i][texcoords[i].length] = 0.5; - texcoords[i][texcoords[i].length] = (data[i][j] - datamin) / datadelta; + texcoords[i] = new Float32Array(x.length * 2); + for(var j = 0, index = 0; j < x.length; j++){ + texcoords[i][index++] = 0.5; + texcoords[i][index++] = (data[i][j] - datamin) / datadelta; } } //linearize the elements array: var element; - for(var i = 0; i < elements.length; i++){ + for(var i = 0, iindex = 0; i < elements.length; i++){ element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1]; if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue; - indices[indices.length] = element[0]; - indices[indices.length] = element[1]; - indices[indices.length] = element[2]; + indices[iindex++] = element[0]; + indices[iindex++] = element[1]; + indices[iindex++] = element[2]; } - indices.itemSize = 1; //Initialize movie loop node["movieInterval"] = 1000 / canvas.moviefps; node["movieTimestamps"] = timestamps; node["movieLength"] = timestamps.length; node["movieFrame"] = 0; - if (canvas["movieHandler"]) clearInterval(canvas["movieHandler"]); canvas["movieHandler"] = setInterval(function () { node["movieFrame"] = canvas["movieFrame"]; if (canvas["moviePlay"] && canvas["movieIncrement"]) { - if (canvas["movieReverse"]) { - node["movieFrame"] = (((node["movieFrame"] - 1) % node["movieLength"]) + node["movieLength"]) % node["movieLength"]; //Handle negative modulus - } - else { - node["movieFrame"] = (((node["movieFrame"] + 1) % node["movieLength"]) + node["movieLength"]) % node["movieLength"]; //Handle negative modulus - } + if (canvas["movieReverse"]) node["movieFrame"] = (((node["movieFrame"] - 1) % node["movieLength"]) + node["movieLength"]) % node["movieLength"]; //Handle negative modulus + else node["movieFrame"] = (((node["movieFrame"] + 1) % node["movieLength"]) + node["movieLength"]) % node["movieLength"]; //Handle negative modulus } - if (canvas["timeLabel"]) { - canvas["timeLabel"].html(node["movieTimestamps"][node["movieFrame"]].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); - } + if (canvas["timeLabel"]) canvas["timeLabel"].html(node["movieTimestamps"][node["movieFrame"]].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); if (canvas["progressBar"]) { canvas["progressBar"].val(node["movieFrame"]); canvas["progressBar"].slider('refresh'); } - node["buffers"] = node["buffersArray"][node["movieFrame"]]; canvas["movieFrame"] = node["movieFrame"]; + var buffer = node["mesh"].getBuffer("coords"); + buffer.data = texcoords[node["movieFrame"]]; + buffer.upload(gl.DYNAMIC_DRAW); }, node["movieInterval"]); if (canvas["progressBar"]) { canvas["movieFrame"] = 0; @@ -270,14 +244,7 @@ canvas["progressBar"].slider('refresh'); } } - - //Initialize buffers - node["arrays"] = [vertices, texcoords, indices]; - node["buffersArray"] = []; - for(var i = 0; i < timestamps.length; i++){ - node["buffersArray"][i] = initBuffers(gl,[node["arrays"][0],node["arrays"][1][i],node["arrays"][2]]); - } - node["buffers"] = node["buffersArray"][0]; + node["mesh"] = GL.Mesh.load({vertices:vertices, coords:texcoords[0], indices:indices}); break; //}}} default: