diff --git a/.npmignore b/.npmignore index 9f5f00e..24fd503 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,5 @@ !/vgl.js !/vgl.min.js !/vgl.min.js.map +!src/**/* .eslintcache diff --git a/CMakeLists.txt b/CMakeLists.txt index dc7d26b..24aca67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,27 @@ configure_file( configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testing/test-runners/vgl_test_runner.py.in ${CMAKE_CURRENT_BINARY_DIR}/test/vgl_test_runner.py ) - +# Fetch Jasmine files +file( + DOWNLOAD https://jasmine.github.io/css/docco.css + ${VGL_DEPLOY_DIR}/test/lib/jasmine/docco.css +) +file( + DOWNLOAD https://jasmine.github.io/css/jasmine_docco.css + ${VGL_DEPLOY_DIR}/test/lib/jasmine/jasmine_docco.css +) +file( + DOWNLOAD https://jasmine.github.io/2.0/lib/jasmine.css + ${VGL_DEPLOY_DIR}/test/lib/jasmine/jasmine.css +) +file( + DOWNLOAD https://jasmine.github.io/2.0/lib/jasmine.js + ${VGL_DEPLOY_DIR}/test/lib/jasmine/jasmine.js +) +file( + DOWNLOAD https://jasmine.github.io/2.0/lib/jasmine-html.js + ${VGL_DEPLOY_DIR}/test/lib/jasmine/jasmine-html.js +) if (COVERAGE_TESTS) set(SOURCES_INCLUDE ) diff --git a/package.json b/package.json index bea2225..5a29f3d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vgl", "description": "VTK for the Web.", - "version": "0.3.7", + "version": "0.3.11", "license": "Apache-2.0", "repository": { "type": "git", @@ -31,13 +31,13 @@ "grunt-parallel": "~0.4", "grunt-template": "~0.2", "grunt-umd": "^2.3.5", - "jquery": "^2.2", + "jquery": "^3.3", "phantomjs": "~1.9", "phantomjs-polyfill": "0.0.1", "xmlbuilder": "^4.1.0" }, "scripts": { - "mypublish": "grunt default test && cp dist/vgl* . && npm publish", + "mypublish": "grunt default && cp dist/vgl{.min,}.js . && npm publish", "test": "grunt test", "build": "grunt default", "lint": "eslint --cache src Gruntfile.js" diff --git a/sources.json b/sources.json index 3957de9..d038c86 100644 --- a/sources.json +++ b/sources.json @@ -28,7 +28,6 @@ "camera.js", "interactorStyle.js", "trackballInteractorStyle.js", - "pvwInteractorStyle.js", "viewer.js", "shader.js", "shaderProgram.js", @@ -43,8 +42,7 @@ "picker.js", "shapefileReader.js", "vtkReader.js", - "dataBuffers.js", - "depthPeelRenderer.js" + "dataBuffers.js" ] } } diff --git a/src/depthPeelRenderer.js b/src/depthPeelRenderer.js deleted file mode 100644 index a1f4084..0000000 --- a/src/depthPeelRenderer.js +++ /dev/null @@ -1,490 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -/** - * Create a new instance of class renderer * - * - * @returns {vgl.renderer} - */ -//////////////////////////////////////////////////////////////////////////// - -vgl.depthPeelRenderer = function () { - 'use strict'; - - if (!(this instanceof vgl.depthPeelRenderer)) { - return new vgl.depthPeelRenderer(); - } - vgl.renderer.call(this); - - var m_this = this, fbo = [], texID = [], depthTexID = [], - colorBlenderTexID, colorBlenderFBOID, setupTime = vgl.timestamp(), - fpMaterial = vgl.material(), blMaterial = vgl.material(), - fiMaterial = vgl.material(), frontPeelShader = null, blendShader = null, - finalShader, NUM_PASSES = 6, m_quad = null, fpwidth, fpheight, blwidth, blheight, - fiwidth, fiheight, fpopacity, fibackgroundColor; - - function drawFullScreenQuad(renderState, material) { - m_quad.setMaterial(material); - - renderState.m_mapper = m_quad.mapper(); - renderState.m_material = material; - - renderState.m_material.bind(renderState); - renderState.m_mapper.render(renderState); - renderState.m_material.undoBind(renderState); - - m_quad.setMaterial(null); - } - - function initScreenQuad(renderState, width, height) { - console.log(width); - console.log(height); - m_quad = vgl.utils.createPlane(0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0); - } - - function initShaders(renderState) { - var fpmv, fpproj, fpvertex, fpcolor, fpdepthTex, fpnormal, fpnr, - blvertex, blColorSamp, blPrevDepthSamp, blCurrDepthSamp, - fivertex, fitempTex; - - // Load the front to back peeling shader - fpvertex = new vgl.vertexAttribute('vertexPosition'); - fpnormal = new vgl.vertexAttribute('vertexNormal'); - fpcolor = new vgl.vertexAttribute('vertexColor'); - fpmv = new vgl.modelViewUniform('modelViewMatrix'); - fpnr = new vgl.modelViewUniform('normalMatrix'); - fpproj = new vgl.projectionUniform('projectionMatrix'); - fpwidth = new vgl.floatUniform('width'); - fpheight = new vgl.floatUniform('height'); - fpopacity = new vgl.floatUniform('opacity', 1.0); - fpdepthTex = new vgl.uniform(vgl.GL.INT, 'depthTexture'); - fpdepthTex.set(0); - - frontPeelShader = new vgl.shaderProgram(); - frontPeelShader.loadShader(vgl.GL.VERTEX_SHADER, 'front_peel.vert'); - frontPeelShader.loadShader(vgl.GL.FRAGMENT_SHADER, 'front_peel.frag'); - - frontPeelShader.addUniform(fpmv); - frontPeelShader.addUniform(fpnr); - frontPeelShader.addUniform(fpproj); - frontPeelShader.addUniform(fpdepthTex); - frontPeelShader.addUniform(fpwidth); - frontPeelShader.addUniform(fpheight); - frontPeelShader.addUniform(fpopacity); - frontPeelShader.addVertexAttribute(fpvertex, vgl.vertexAttributeKeys.Position); - frontPeelShader.addVertexAttribute(fpnormal, vgl.vertexAttributeKeys.Normal); - frontPeelShader.addVertexAttribute(fpcolor, vgl.vertexAttributeKeys.Color); - - // Compile and link the shader - frontPeelShader.compileAndLink(renderState); - - fpMaterial.addAttribute(frontPeelShader); - - // //add attributes and uniforms - // frontPeelShader.AddAttribute('vVertex'); - // frontPeelShader.AddUniform('MVP'); - // frontPeelShader.AddUniform('vColor'); - // frontPeelShader.AddUniform('depthTexture'); - // //pass constant uniforms at initialization - // glUniform1i(frontPeelShader('depthTexture'), 0); - // frontPeelShader.UnUse(); - - // Load the blending shader - blendShader = new vgl.shaderProgram(); - blendShader.loadShader(vgl.GL.VERTEX_SHADER, 'blend.vert'); - blendShader.loadShader(vgl.GL.FRAGMENT_SHADER, 'blend.frag'); - blColorSamp = new vgl.uniform(vgl.GL.INT, 'currColorTexture'); - blPrevDepthSamp = new vgl.uniform(vgl.GL.INT, 'prevDepthTexture'); - blCurrDepthSamp = new vgl.uniform(vgl.GL.INT, 'currDepthTexture'); - - blwidth = new vgl.floatUniform('width'); - blheight = new vgl.floatUniform('height'); - blColorSamp.set(0); - blPrevDepthSamp.set(1); - blCurrDepthSamp.set(2); - - blvertex = new vgl.vertexAttribute('vertexPosition'); - - blendShader.addUniform(blColorSamp); - blendShader.addUniform(blPrevDepthSamp); - blendShader.addUniform(blPrevDepthSamp); - blendShader.addUniform(blwidth); - blendShader.addUniform(blheight); - blendShader.addVertexAttribute(blvertex, - vgl.vertexAttributeKeys.Position); - - // Compile and link the shader - blendShader.compileAndLink(renderState); - blMaterial.addAttribute(blendShader); - - // //add attributes and uniforms - // blendShader.AddAttribute('vVertex'); - // blendShader.AddUniform('currColorTexture'); - // //pass constant uniforms at initialization - // glUniform1i(blendShader('currColorTexture'), 0); - // blendShader.UnUse(); - - //Load the final shader - finalShader = new vgl.shaderProgram(); - finalShader.loadShader(vgl.GL.VERTEX_SHADER, 'blend.vert'); - finalShader.loadShader(vgl.GL.FRAGMENT_SHADER, 'final.frag'); - - //fimv = new vgl.modelViewUniform('modelViewMatrix'); - //fiproj = new vgl.projectionUniform('projectionMatrix'); - fitempTex = new vgl.uniform(vgl.GL.INT, 'colorTexture'); - fiwidth = new vgl.floatUniform('width'); - fiheight = new vgl.floatUniform('height'); - fibackgroundColor = new vgl.uniform(vgl.GL.FLOAT_VEC3, 'backgroundColor'); - fitempTex.set(0); - fivertex = new vgl.vertexAttribute('vertexPosition'); - - //finalShader.addUniform(fimv); - //finalShader.addUniform(fiproj); - finalShader.addUniform(fitempTex); - finalShader.addUniform(fiwidth); - finalShader.addUniform(fiheight); - finalShader.addUniform(fibackgroundColor); - finalShader.addVertexAttribute(fivertex, vgl.vertexAttributeKeys.Position); - finalShader.compileAndLink(renderState); - fiMaterial.addAttribute(finalShader); - } - - function initFBO(renderState, WIDTH, HEIGHT) { - var i, textureFloatExt, textureFloatLinearExt, depthTextureExt, filtering; - - // Or browser-appropriate prefix - depthTextureExt = renderState.m_context.getExtension('WEBKIT_WEBGL_depth_texture'); - if (!depthTextureExt) { - depthTextureExt = renderState.m_context.getExtension('WEBGL_depth_texture'); - - if (!depthTextureExt) { - console.log('Depth textures are not supported'); - } - } - - var floatTextureExt = renderState.m_context.getExtension('OES_texture_float'); - if (!floatTextureExt) { - console.log('float textures are not supported'); - } - - textureFloatExt = renderState.m_context.getExtension('OES_texture_float'); - if (!textureFloatExt) { - console.log('Extension Texture Float is not working'); - window.alert(':( Sorry, Your browser doesn\'t support texture float extension.'); - return; - } - textureFloatLinearExt = renderState.m_context.getExtension( - 'OES_texture_float_linear'); - depthTextureExt = renderState.m_context.getExtension('WEBGL_depth_texture'); - - if (!depthTextureExt) { - console.log('Extension Depth texture is not working'); - window.alert(':( Sorry, Your browser doesn\'t support depth texture extension.'); - return; - } - - filtering = textureFloatLinearExt ? vgl.GL.LINEAR : vgl.GL.NEAREST; - - //FBO initialization function - // Generate 2 FBO - fbo.push(renderState.m_context.createFramebuffer()); - fbo.push(renderState.m_context.createFramebuffer()); - - // Create two textures - texID.push(renderState.m_context.createTexture()); - texID.push(renderState.m_context.createTexture()); - - //The FBO has two depth attachments - depthTexID.push(renderState.m_context.createTexture()); - depthTexID.push(renderState.m_context.createTexture()); - - // For each attachment - for (i = 0; i < 2; i += 1) { - // First initialize the depth texture - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, depthTexID[i]); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_MAG_FILTER, vgl.GL.NEAREST); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_MIN_FILTER, vgl.GL.NEAREST); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_WRAP_S, vgl.GL.CLAMP_TO_EDGE); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_WRAP_T, vgl.GL.CLAMP_TO_EDGE); - renderState.m_context.texImage2D(vgl.GL.TEXTURE_2D, 0, - vgl.GL.DEPTH_COMPONENT, WIDTH, HEIGHT, 0, vgl.GL.DEPTH_COMPONENT, - vgl.GL.UNSIGNED_SHORT, null); - - // Second initialize the color attachment - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, texID[i]); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_MAG_FILTER, filtering); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_MIN_FILTER, filtering); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_WRAP_S, vgl.GL.CLAMP_TO_EDGE); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_WRAP_T, vgl.GL.CLAMP_TO_EDGE); - renderState.m_context.texImage2D(vgl.GL.TEXTURE_2D, 0, vgl.GL.RGBA, - WIDTH, HEIGHT, 0, vgl.GL.RGBA, vgl.GL.FLOAT, null); - - // Bind FBO and attach the depth and color attachments - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, fbo[i]); - renderState.m_context.framebufferTexture2D(vgl.GL.FRAMEBUFFER, - vgl.GL.DEPTH_ATTACHMENT, vgl.GL.TEXTURE_2D, depthTexID[i], 0); - renderState.m_context.framebufferTexture2D(vgl.GL.FRAMEBUFFER, - vgl.GL.COLOR_ATTACHMENT0, vgl.GL.TEXTURE_2D, texID[i], 0); - } - - // Now setup the color attachment for color blend FBO - colorBlenderTexID = renderState.m_context.createTexture(); - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, colorBlenderTexID); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_WRAP_S, vgl.GL.CLAMP_TO_EDGE); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_WRAP_T, vgl.GL.CLAMP_TO_EDGE); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_MIN_FILTER, vgl.GL.NEAREST); - renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, - vgl.GL.TEXTURE_MAG_FILTER, vgl.GL.NEAREST); - renderState.m_context.texImage2D(vgl.GL.TEXTURE_2D, 0, vgl.GL.RGBA, - WIDTH, HEIGHT, 0, vgl.GL.RGBA, vgl.GL.FLOAT, null); - - // Generate the color blend FBO ID - colorBlenderFBOID = renderState.m_context.createFramebuffer(); - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, colorBlenderFBOID); - - // Set the depth attachment of previous FBO as depth attachment for this FBO - renderState.m_context.framebufferTexture2D(vgl.GL.FRAMEBUFFER, - vgl.GL.DEPTH_ATTACHMENT, vgl.GL.TEXTURE_2D, depthTexID[0], 0); - - // Set the color blender texture as the FBO color attachment - renderState.m_context.framebufferTexture2D(vgl.GL.FRAMEBUFFER, - vgl.GL.COLOR_ATTACHMENT0, vgl.GL.TEXTURE_2D, colorBlenderTexID, 0); - - // Check the FBO completeness status - var status = renderState.m_context.checkFramebufferStatus( - vgl.GL.FRAMEBUFFER); - if (status === vgl.GL.FRAMEBUFFER_COMPLETE) { - console.log('FBO setup successful !!! \n'); - } else { - console.log('Problem with FBO setup'); - } - // Unbind FBO - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, null); - } - - function setup(renderState) { - if (setupTime.getMTime() < m_this.getMTime()) { - initScreenQuad(renderState, m_this.width(), m_this.height()); - initShaders(renderState, m_this.width(), m_this.height()); - initFBO(renderState, m_this.width(), m_this.height()); - setupTime.modified(); - } - } - - function drawScene(renderState, sortedActors, material) { - - var i, actor, mvMatrixInv = mat4.create(); - - // // Enable alpha blending with over compositing - // gl.enable(vgl.GL.BLEND); - // gl.blendFunc(vgl.GL.SRC_ALPHA, vgl.GL.ONE_MINUS_SRC_ALPHA); - - for (i = 0; i < sortedActors.length; i += 1) { - actor = sortedActors[i][2]; - - if (actor.referenceFrame() === - vgl.boundingObject.ReferenceFrame.Relative) { - mat4.multiply(renderState.m_modelViewMatrix, m_this.m_camera.viewMatrix(), - actor.matrix()); - renderState.m_projectionMatrix = m_this.m_camera.projectionMatrix(); - } else { - renderState.m_modelViewMatrix = actor.matrix(); - renderState.m_projectionMatrix = mat4.create(); - mat4.ortho(renderState.m_projectionMatrix, 0, - m_this.m_width, 0, m_this.m_height, -1, 1); - } - - mat4.invert(mvMatrixInv, renderState.m_modelViewMatrix); - mat4.transpose(renderState.m_normalMatrix, mvMatrixInv); - renderState.m_mapper = actor.mapper(); - - // TODO Fix this shortcut - if (!material) { - renderState.m_material = actor.material(); - renderState.m_material.bind(renderState); - renderState.m_mapper.render(renderState); - renderState.m_material.undoBind(renderState); - } else { - - var ou = actor.material().shaderProgram().uniform('opacity'); - if (ou) { - fpopacity.set(ou.get()[0]); - } else { - fpopacity.set(1.0); - } - renderState.m_material = material; - renderState.m_material.bind(renderState); - renderState.m_mapper.render(renderState); - renderState.m_material.undoBind(renderState); - } - } - } - - function depthPeelRender(renderState, actors) { - var layer; - - fpwidth.set(m_this.width()); - fpheight.set(m_this.height()); - blwidth.set(m_this.width()); - blheight.set(m_this.height()); - fiwidth.set(m_this.width()); - fiheight.set(m_this.height()); - - // Clear color and depth buffer - renderState.m_context.clearColor(0.0, 0.0, 0.0, 0.0); - /*jshint bitwise: false */ - renderState.m_context.clear(vgl.GL.OLOR_BUFFER_BIT | vgl.GL.DEPTH_BUFFER_BIT); - /*jshint bitwise: true */ - - // Bind the color blending FBO - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, colorBlenderFBOID); - - // 1. In the first pass, we render normally with depth test enabled to - // get the nearest surface - renderState.m_context.enable(vgl.GL.DEPTH_TEST); - renderState.m_context.disable(vgl.GL.BLEND); - - var clearColor = m_this.m_camera.clearColor(); - renderState.m_context.clearColor(clearColor[0], clearColor[1], clearColor[2], 0.0); - /*jshint bitwise: false */ - renderState.m_context.clear(vgl.GL.COLOR_BUFFER_BIT | vgl.GL.DEPTH_BUFFER_BIT); - /*jshint bitwise: true */ - - drawScene(renderState, actors); - - // 2. Depth peeling + blending pass - var numLayers = (NUM_PASSES - 1) * 2; - - // For each pass - for (layer = 1; layer < numLayers; layer += 1) { - var currId = layer % 2; - var prevId = 1 - currId; - - // Bind the current FBO - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, fbo[currId]); - - // Disbale blending and enable depth testing - renderState.m_context.disable(vgl.GL.BLEND); - renderState.m_context.enable(vgl.GL.DEPTH_TEST); - - // Bind the depth texture from the previous step - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, depthTexID[prevId]); - - // Set clear color to black - renderState.m_context.clearColor(0.0, 0.0, 0.0, 0.0); - - // Clear the color and depth buffers - /*jshint bitwise: false */ - renderState.m_context.clear(vgl.GL.COLOR_BUFFER_BIT | vgl.GL.DEPTH_BUFFER_BIT); - /*jshint bitwise: true */ - - // Render scene with the front to back peeling shader - drawScene(renderState, actors, fpMaterial); - - // Bind the color blender FBO - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, colorBlenderFBOID); - - // Enable blending but disable depth testing - renderState.m_context.disable(vgl.GL.DEPTH_TEST); - renderState.m_context.enable(vgl.GL.BLEND); - - // Change the blending equation to add - renderState.m_context.blendEquation(vgl.GL.FUNC_ADD); - - // Use separate blending function - renderState.m_context.blendFuncSeparate(vgl.GL.DST_ALPHA, vgl.GL.ONE, - vgl.GL.ZERO, vgl.GL.ONE_MINUS_SRC_ALPHA); - - // Bind the result from the previous iteration as texture - renderState.m_context.activeTexture(vgl.GL.TEXTURE0); - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, texID[currId]); - - renderState.m_context.activeTexture(vgl.GL.TEXTURE1); - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, depthTexID[prevId]); - - renderState.m_context.activeTexture(vgl.GL.TEXTURE2); - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, depthTexID[currId]); - - drawFullScreenQuad(renderState, blMaterial); - - renderState.m_context.activeTexture(vgl.GL.TEXTURE0); - - // Disable blending - renderState.m_context.disable(vgl.GL.BLEND); - } - - // 3. Final render pass - //remove the FBO - renderState.m_context.bindFramebuffer(vgl.GL.FRAMEBUFFER, null); - - // Disable depth testing and blending - renderState.m_context.disable(vgl.GL.DEPTH_TEST); - renderState.m_context.disable(vgl.GL.BLEND); - - // Bind the color blender texture - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, colorBlenderTexID); - - fibackgroundColor.set(m_this.m_camera.clearColor()); - - // Draw full screen quad - drawFullScreenQuad(renderState, fiMaterial); - - renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, null); - } - - //////////////////////////////////////////////////////////////////////////// - /** - * Render the scene - */ - //////////////////////////////////////////////////////////////////////////// - this.render = function () { - var i, renSt, children, actor = null, sortedActors = []; - - renSt = new vgl.renderState(); - renSt.m_renderer = m_this; - renSt.m_context = m_this.renderWindow().context(); - renSt.m_contextChanged = m_this.m_contextChanged; - - // Set the viewport for this renderer - renSt.m_context.viewport(m_this.m_x, m_this.m_y, m_this.m_width, m_this.m_height); - - // Check if we have initialized - setup(renSt); - - children = m_this.m_sceneRoot.children(); - - if (children.length > 0 && m_this.m_resetScene) { - this.resetCamera(); - m_this.m_resetScene = false; - } - - for (i = 0; i < children.length; i += 1) { - actor = children[i]; - actor.computeBounds(); - if (actor.visible()) { - sortedActors.push([actor.material().binNumber(), - actor.material().shaderProgram().uniform('opacity').get()[0], - actor]); - } - } - - // Now perform sorting - sortedActors.sort(function (a, b) { return a[0] - b[0]; }); - sortedActors.sort(function (a, b) { return b[1] - a[1]; }); - - depthPeelRender(renSt, sortedActors); - }; -}; - -inherit(vgl.depthPeelRenderer, vgl.renderer); diff --git a/src/mapper.js b/src/mapper.js index 88fea09..d96a36d 100644 --- a/src/mapper.js +++ b/src/mapper.js @@ -52,6 +52,12 @@ vgl.mapper = function (arg) { } }; + this._cleanup = function (renderState) { + m_this.deleteVertexBufferObjects(renderState); + cleanUpDrawObjects(renderState); + m_this.modified(); + }; + //////////////////////////////////////////////////////////////////////////// /** * Create new VBO for all its geometryData sources and primitives @@ -302,10 +308,12 @@ vgl.mapper = function (arg) { } noOfPrimitives = m_geomData.numberOfPrimitives(); - for (j = 0; j < noOfPrimitives; j += 1) { - m_context.bindBuffer(vgl.GL.ARRAY_BUFFER, m_buffers[bufferIndex]); - bufferIndex += 1; + for (j = 0; j < noOfPrimitives; j += 1, bufferIndex += 1) { primitive = m_geomData.primitive(j); + if (!primitive.numberOfIndices()) { + continue; + } + m_context.bindBuffer(vgl.GL.ARRAY_BUFFER, m_buffers[bufferIndex]); switch (primitive.primitiveType()) { case vgl.GL.POINTS: m_context.drawArrays(vgl.GL.POINTS, 0, primitive.numberOfIndices()); diff --git a/src/material.js b/src/material.js index 4cac302..ff6bb01 100644 --- a/src/material.js +++ b/src/material.js @@ -211,6 +211,8 @@ vgl.material = function () { m_textureAttributes[key]._cleanup(renderState); } } + m_shaderProgram._cleanup(renderState); + m_this.modified(); }; //////////////////////////////////////////////////////////////////////////// diff --git a/src/pvwInteractorStyle.js b/src/pvwInteractorStyle.js deleted file mode 100644 index 10f89a7..0000000 --- a/src/pvwInteractorStyle.js +++ /dev/null @@ -1,214 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -/** - * @module vgl - */ - -/*global vgl, vec4, inherit*/ -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -/** - * Create a new instance of pvwInteractorStyle (for ParaViewWeb) - * - * @class vgl.pvwInteractorStyle - * @returns {vgl.pvwInteractorStyle} - */ -////////////////////////////////////////////////////////////////////////////// -vgl.pvwInteractorStyle = function () { - 'use strict'; - - if (!(this instanceof vgl.pvwInteractorStyle)) { - return new vgl.pvwInteractorStyle(); - } - vgl.trackballInteractorStyle.call(this); - var m_that = this, - m_leftMouseButtonDown = false, - m_rightMouseButtonDown = false, - m_middleMouseButtonDown = false, - m_width, - m_height, - m_renderer, - m_camera, - m_outsideCanvas, - m_coords, - m_currentMousePos, - m_focalPoint, - m_focusWorldPt, - m_focusDisplayPt, - m_displayPt1, - m_displayPt2, - m_worldPt1, - m_worldPt2, - m_dx, - m_dy, - m_dz, - m_zTrans, - m_mouseLastPos = { - x: 0, - y: 0 - }; - - function render() { - m_renderer.resetCameraClippingRange(); - m_that.viewer().render(); - } - - ///////////////////////////////////////////////////////////////////////////// - /** - * Handle mouse move event - * - * @param event - * @returns {boolean} - */ - ///////////////////////////////////////////////////////////////////////////// - this.handleMouseMove = function (event) { - var rens = [], i = null, secCameras = [], deltaxy = null; - m_width = m_that.viewer().renderWindow().windowSize()[0]; - m_height = m_that.viewer().renderWindow().windowSize()[1]; - m_renderer = m_that.viewer().renderWindow().activeRenderer(); - m_camera = m_renderer.camera(); - m_outsideCanvas = false; - m_coords = m_that.viewer().relMouseCoords(event); - m_currentMousePos = { - x: 0, - y: 0 - }; - - // Get secondary cameras - rens = m_that.viewer().renderWindow().renderers(); - for (i = 0; i < rens.length; i += 1) { - if (m_renderer !== rens[i]) { - secCameras.push(rens[i].camera()); - } - } - - if ((m_coords.x < 0) || (m_coords.x > m_width)) { - m_currentMousePos.x = 0; - m_outsideCanvas = true; - } else { - m_currentMousePos.x = m_coords.x; - } - if ((m_coords.y < 0) || (m_coords.y > m_height)) { - m_currentMousePos.y = 0; - m_outsideCanvas = true; - } else { - m_currentMousePos.y = m_coords.y; - } - if (m_outsideCanvas === true) { - return; - } - m_focalPoint = m_camera.focalPoint(); - m_focusWorldPt = vec4.fromValues(m_focalPoint[0], m_focalPoint[1], - m_focalPoint[2], 1); - m_focusDisplayPt = m_renderer.worldToDisplay(m_focusWorldPt, - m_camera.viewMatrix(), m_camera.projectionMatrix(), m_width, m_height); - m_displayPt1 = vec4.fromValues( - m_currentMousePos.x, m_currentMousePos.y, m_focusDisplayPt[2], 1.0); - m_displayPt2 = vec4.fromValues( - m_mouseLastPos.x, m_mouseLastPos.y, m_focusDisplayPt[2], 1.0); - m_worldPt1 = m_renderer.displayToWorld( - m_displayPt1, m_camera.viewMatrix(), m_camera.projectionMatrix(), - m_width, m_height); - m_worldPt2 = m_renderer.displayToWorld( - m_displayPt2, m_camera.viewMatrix(), m_camera.projectionMatrix(), - m_width, m_height); - - m_dx = m_worldPt1[0] - m_worldPt2[0]; - m_dy = m_worldPt1[1] - m_worldPt2[1]; - m_dz = m_worldPt1[2] - m_worldPt2[2]; - - if (m_middleMouseButtonDown) { - m_camera.pan(-m_dx, -m_dy, -m_dz); - render(); - } - if (m_leftMouseButtonDown) { - deltaxy = [(m_mouseLastPos.x - m_currentMousePos.x), - (m_mouseLastPos.y - m_currentMousePos.y)]; - m_camera.rotate(deltaxy[0], deltaxy[1]); - - // Apply rotation to all other cameras - for (i = 0; i < secCameras.length; i += 1) { - secCameras[i].rotate(deltaxy[0], deltaxy[1]); - } - - // Apply rotation to all other cameras - for (i = 0; i < rens.length; i += 1) { - rens[i].resetCameraClippingRange(); - } - render(); - } - if (m_rightMouseButtonDown) { - /// 2.0 is the speed up factor. - m_zTrans = 2.0 * (m_currentMousePos.y - m_mouseLastPos.y) / m_height; - - // Calculate zoom scale here - if (m_zTrans > 0) { - m_camera.zoom(1 - Math.abs(m_zTrans)); - } else { - m_camera.zoom(1 + Math.abs(m_zTrans)); - } - render(); - } - m_mouseLastPos.x = m_currentMousePos.x; - m_mouseLastPos.y = m_currentMousePos.y; - return false; - }; - - ///////////////////////////////////////////////////////////////////////////// - /** - * Handle mouse down event - * - * @param event - * @returns {boolean} - */ - ///////////////////////////////////////////////////////////////////////////// - this.handleMouseDown = function (event) { - if (event.button === 0) { - m_leftMouseButtonDown = true; - } - if (event.button === 1) { - m_middleMouseButtonDown = true; - } - if (event.button === 2) { - m_rightMouseButtonDown = true; - } - m_coords = m_that.viewer().relMouseCoords(event); - if (m_coords.x < 0) { - m_mouseLastPos.x = 0; - } else { - m_mouseLastPos.x = m_coords.x; - } - if (m_coords.y < 0) { - m_mouseLastPos.y = 0; - } else { - m_mouseLastPos.y = m_coords.y; - } - return false; - }; - - // @note We never get mouse up from scroll bar: See the bug report here - // http://bugs.jquery.com/ticket/8184 - ///////////////////////////////////////////////////////////////////////////// - /** - * Handle mouse up event - * - * @param event - * @returns {boolean} - */ - ///////////////////////////////////////////////////////////////////////////// - this.handleMouseUp = function (event) { - if (event.button === 0) { - m_leftMouseButtonDown = false; - } - if (event.button === 1) { - m_middleMouseButtonDown = false; - } - if (event.button === 2) { - m_rightMouseButtonDown = false; - } - return false; - }; - - return this; -}; -inherit(vgl.pvwInteractorStyle, vgl.trackballInteractorStyle); diff --git a/src/renderWindow.js b/src/renderWindow.js index 564ee32..fbec24d 100644 --- a/src/renderWindow.js +++ b/src/renderWindow.js @@ -294,6 +294,7 @@ vgl.renderWindow = function (canvas) { m_renderers[i]._cleanup(renderState); } vgl.clearCachedShaders(renderState ? renderState.m_context : null); + m_this.modified(); }; //////////////////////////////////////////////////////////////////////////// diff --git a/src/renderer.js b/src/renderer.js index 4b27b7e..17fc5c9 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -298,6 +298,7 @@ vgl.renderer = function (arg) { renSt.m_context.finish(); m_this.m_contextChanged = false; + m_this.m_lastRenderState = renSt; }; //////////////////////////////////////////////////////////////////////////// @@ -561,10 +562,15 @@ vgl.renderer = function (arg) { if (m_this.m_sceneRoot.children().indexOf(actor) !== -1) { /* When we remove an actor, free the VBOs of the mapper and mark the * mapper as modified; it will reallocate VBOs as necessary. */ - if (actor.mapper()) { - actor.mapper().deleteVertexBufferObjects(); - actor.mapper().modified(); + if (m_this.m_lastRenderState) { + if (actor.mapper()) { + actor.mapper()._cleanup(m_this.m_lastRenderState); + } + if (actor.material()) { + actor.material()._cleanup(m_this.m_lastRenderState); + } } + actor.modified(); m_this.m_sceneRoot.removeChild(actor); m_this.modified(); return true; @@ -785,6 +791,7 @@ vgl.renderer = function (arg) { } m_this.m_sceneRoot.removeChildren(); + m_this.modified(); }; return m_this; diff --git a/src/shaderProgram.js b/src/shaderProgram.js index 5d44b93..8a9b0d0 100644 --- a/src/shaderProgram.js +++ b/src/shaderProgram.js @@ -276,6 +276,7 @@ vgl.shaderProgram = function () { this._cleanup = function (renderState) { m_this.deleteVertexAndFragment(renderState); m_this.deleteProgram(renderState); + m_this.modified(); }; ///////////////////////////////////////////////////////////////////////////// @@ -284,7 +285,9 @@ vgl.shaderProgram = function () { */ ///////////////////////////////////////////////////////////////////////////// this.deleteProgram = function (renderState) { - renderState.m_context.deleteProgram(m_programHandle); + if (m_programHandle) { + renderState.m_context.deleteProgram(m_programHandle); + } m_programHandle = 0; }; @@ -296,7 +299,9 @@ vgl.shaderProgram = function () { this.deleteVertexAndFragment = function (renderState) { var i; for (i = 0; i < m_shaders.length; i += 1) { - renderState.m_context.detachShader(m_shaders[i].shaderHandle(renderState)); + if (m_shaders[i].shaderHandle(renderState)) { + renderState.m_context.detachShader(m_programHandle, m_shaders[i].shaderHandle(renderState)); + } renderState.m_context.deleteShader(m_shaders[i].shaderHandle(renderState)); m_shaders[i].removeContext(renderState); } diff --git a/src/uniform.js b/src/uniform.js index a7304e4..136d33f 100644 --- a/src/uniform.js +++ b/src/uniform.js @@ -19,7 +19,7 @@ vgl.uniform = function (type, name) { 'use strict'; if (!(this instanceof vgl.uniform)) { - return new vgl.uniform(); + return new vgl.uniform(type, name); } this.getTypeNumberOfComponents = function (type) { @@ -102,25 +102,9 @@ vgl.uniform = function (type, name) { */ ///////////////////////////////////////////////////////////////////////////// this.set = function (value) { - var i = 0; - if (m_dataArray.length === 16) { - for (i = 0; i < 16; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 9) { - for (i = 0; i < 9; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 4) { - for (i = 0; i < 4; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 3) { - for (i = 0; i < 3; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 2) { - for (i = 0; i < 2; i += 1) { + var i = 0, lendata = m_dataArray.length; + if (lendata !== 1) { + for (i = 0; i < lendata; i += 1) { m_dataArray[i] = value[i]; } } else { @@ -136,10 +120,6 @@ vgl.uniform = function (type, name) { */ ///////////////////////////////////////////////////////////////////////////// this.callGL = function (renderState, location) { - if (this.m_numberElements < 1) { - return; - } - switch (m_type) { case vgl.GL.BOOL: case vgl.GL.INT: @@ -148,12 +128,24 @@ vgl.uniform = function (type, name) { case vgl.GL.FLOAT: renderState.m_context.uniform1fv(location, m_dataArray); break; + case vgl.GL.BOOL_VEC2: + case vgl.GL.INT_VEC2: + renderState.m_context.uniform2iv(location, m_dataArray); + break; case vgl.GL.FLOAT_VEC2: renderState.m_context.uniform2fv(location, m_dataArray); break; + case vgl.GL.BOOL_VEC3: + case vgl.GL.INT_VEC3: + renderState.m_context.uniform3iv(location, m_dataArray); + break; case vgl.GL.FLOAT_VEC3: renderState.m_context.uniform3fv(location, m_dataArray); break; + case vgl.GL.BOOL_VEC4: + case vgl.GL.INT_VEC4: + renderState.m_context.uniform4iv(location, m_dataArray); + break; case vgl.GL.FLOAT_VEC4: renderState.m_context.uniform4fv(location, m_dataArray); break; @@ -179,8 +171,8 @@ vgl.uniform = function (type, name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - renderState = renderState; /* unused parameter */ - program = program; /* unused parameter */ + void renderState; /* unused parameter */ + void program; /* unused parameter */ // Should be implemented by the derived class }; @@ -202,7 +194,7 @@ vgl.modelViewUniform = function (name) { return new vgl.modelViewUniform(name); } - if (name.length === 0) { + if (!name) { name = 'modelViewMatrix'; } @@ -219,7 +211,7 @@ vgl.modelViewUniform = function (name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ + void program; /* unused parameter */ this.set(renderState.m_modelViewMatrix); }; @@ -244,7 +236,7 @@ vgl.modelViewOriginUniform = function (name, origin) { return new vgl.modelViewOriginUniform(name, origin); } - if (name.length === 0) { + if (!name) { name = 'modelViewMatrix'; } origin = origin || [0, 0, 0]; @@ -277,11 +269,15 @@ vgl.modelViewOriginUniform = function (name, origin) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ - var view = mat4.create(); - mat4.translate(view, renderState.m_modelViewMatrix, m_origin); + void program; /* unused parameter */ + var view = renderState.m_modelViewMatrix; if (renderState.m_modelViewAlignment) { + /* adjust alignment before origin. Otherwise, a changing origin can + * affect the rounding choice and result in a 1 pixe jitter. */ var align = renderState.m_modelViewAlignment; + /* Don't modify the orignal matrix. If we are in an environment where + * you can't slice an Float32Array, switch to a regular array */ + view = view.slice ? view.slice() : Array.prototype.slice.call(view); /* view[12] and view[13] are the x and y offsets. align.round is the * units-per-pixel, and align.dx and .dy are either 0 or half the size of * a unit-per-pixel. The alignment guarantees that the texels are @@ -289,6 +285,7 @@ vgl.modelViewOriginUniform = function (name, origin) { view[12] = Math.round(view[12] / align.roundx) * align.roundx + align.dx; view[13] = Math.round(view[13] / align.roundy) * align.roundy + align.dy; } + view = mat4.translate(mat4.create(), view, m_origin); this.set(view); }; @@ -312,7 +309,7 @@ vgl.projectionUniform = function (name) { return new vgl.projectionUniform(name); } - if (name.length === 0) { + if (!name) { name = 'projectionMatrix'; } @@ -329,7 +326,7 @@ vgl.projectionUniform = function (name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ + void program; /* unused parameter */ this.set(renderState.m_projectionMatrix); }; @@ -354,7 +351,7 @@ vgl.floatUniform = function (name, value) { return new vgl.floatUniform(name, value); } - if (name.length === 0) { + if (!name) { name = 'floatUniform'; } @@ -382,7 +379,7 @@ vgl.normalMatrixUniform = function (name) { return new vgl.normalMatrixUniform(name); } - if (name.length === 0) { + if (!name) { name = 'normalMatrix'; } @@ -399,7 +396,7 @@ vgl.normalMatrixUniform = function (name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ + void program; /* unused parameter */ this.set(renderState.m_normalMatrix); }; diff --git a/testing/cases/phantomjs/mapper.js b/testing/cases/phantomjs/mapper.js index 87676fe..fbfff0b 100644 --- a/testing/cases/phantomjs/mapper.js +++ b/testing/cases/phantomjs/mapper.js @@ -128,6 +128,14 @@ describe('vgl.mapper', function () { mapper.geometryData().addSource(src2); mapper.modified(); mapper.render(renderState); + + /* Zero length indices shouldn't generate drawArray calls */ + line.setIndices([]); + point.setIndices([]); + glCounts = $.extend({}, vgl.mockCounts()); + mapper.modified(); + mapper.render(renderState); + expect(vgl.mockCounts().drawArrays).toBe((glCounts.drawArrays || 0) + 3); }); it('deleteVertexBufferObjects', function () { mapper.render(renderState); diff --git a/testing/cases/phantomjs/material.js b/testing/cases/phantomjs/material.js index f905a00..27c2d04 100644 --- a/testing/cases/phantomjs/material.js +++ b/testing/cases/phantomjs/material.js @@ -139,6 +139,8 @@ describe('vgl.material', function () { mat.addAttribute(blend); mat.addAttribute(tex); mat.setAttribute(prog); + mat.bind(renderState); + mat.undoBind(renderState); glCounts = $.extend({}, vgl.mockCounts()); mat._cleanup(renderState); expect(vgl.mockCounts().deleteProgram).toBe((glCounts.deleteProgram || 0) + 1); diff --git a/testing/cases/phantomjs/shaderProgram.js b/testing/cases/phantomjs/shaderProgram.js index c3e5180..901967e 100644 --- a/testing/cases/phantomjs/shaderProgram.js +++ b/testing/cases/phantomjs/shaderProgram.js @@ -127,6 +127,7 @@ describe('vgl.shaderProgram', function () { expect(vgl.mockCounts().useProgram).toBe((glCounts.useProgram || 0) + 1); }); it('deleteProgram', function () { + sp._setup(renderState); glCounts = $.extend({}, vgl.mockCounts()); sp.deleteProgram(renderState); expect(vgl.mockCounts().deleteProgram).toBe((glCounts.deleteProgram || 0) + 1); diff --git a/testing/cases/phantomjs/uniform.js b/testing/cases/phantomjs/uniform.js new file mode 100644 index 0000000..f532ee7 --- /dev/null +++ b/testing/cases/phantomjs/uniform.js @@ -0,0 +1,247 @@ +/*global describe, it, expect, vgl, mockVGLRenderer*/ + +describe('vgl.uniform', function () { + + describe('Create', function () { + it('create function', function () { + var uni = vgl.uniform(); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe(undefined); + expect(uni.type()).toBe(undefined); + expect(uni.get().length).toBe(0); + uni = vgl.uniform(vgl.GL.FLOAT, 'sample'); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('sample'); + expect(uni.type()).toBe(vgl.GL.FLOAT); + expect(uni.get().length).toBe(1); + uni = new vgl.uniform(vgl.GL.INT_VEC2, 'sample2'); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('sample2'); + expect(uni.type()).toBe(vgl.GL.INT_VEC2); + expect(uni.get().length).toBe(2); + }); + }); + describe('Public methods', function () { + var types = [ + {type: vgl.GL.BOOL, comp: 1, uniform: 'uniform1iv'}, + {type: vgl.GL.FLOAT, comp: 1, uniform: 'uniform1fv'}, + {type: vgl.GL.INT, comp: 1, uniform: 'uniform1iv'}, + {type: vgl.GL.BOOL_VEC2, comp: 2, uniform: 'uniform2iv'}, + {type: vgl.GL.FLOAT_VEC2, comp: 2, uniform: 'uniform2fv'}, + {type: vgl.GL.INT_VEC2, comp: 2, uniform: 'uniform2iv'}, + {type: vgl.GL.BOOL_VEC3, comp: 3, uniform: 'uniform3iv'}, + {type: vgl.GL.FLOAT_VEC3, comp: 3, uniform: 'uniform3fv'}, + {type: vgl.GL.INT_VEC3, comp: 3, uniform: 'uniform3iv'}, + {type: vgl.GL.BOOL_VEC4, comp: 4, uniform: 'uniform4iv'}, + {type: vgl.GL.FLOAT_VEC4, comp: 4, uniform: 'uniform4fv'}, + {type: vgl.GL.INT_VEC4, comp: 4, uniform: 'uniform4iv'}, + {type: vgl.GL.FLOAT_MAT3, comp: 9, uniform: 'uniformMatrix3fv'}, + {type: vgl.GL.FLOAT_MAT4, comp: 16, uniform: 'uniformMatrix4fv'}, + {type: 'unknown', comp: 0} + ]; + it('getTypeNumberOfComponents', function () { + var uni = vgl.uniform(), i; + for (i = 0; i < types.length; i += 1) { + expect(uni.getTypeNumberOfComponents(types[i].type)).toBe(types[i].comp); + } + }); + it('name', function () { + var uni, i; + for (i = 0; i < types.length; i += 1) { + uni = vgl.uniform(types[i].type, 'uniform_' + i); + expect(uni.name()).toBe('uniform_' + i); + } + }); + it('type', function () { + var uni, i; + for (i = 0; i < types.length; i += 1) { + uni = vgl.uniform(types[i].type, 'uniform_' + i); + expect(uni.type()).toBe(types[i].type); + } + }); + it('set and get', function () { + var uni, i, j, counter = 0, data; + for (i = 0; i < types.length; i += 1) { + uni = vgl.uniform(types[i].type, 'uniform_' + i); + data = new Array(types[i].comp); + for (j = 0; j < types[i].comp; j += 1, counter += 1) { + data[j] = counter; + } + if (types[i].comp !== 1) { + uni.set(data); + } else { + uni.set(data[0]); + } + expect(uni.get()).toEqual(data); + } + }); + it('callGL', function () { + mockVGLRenderer(); + var viewer = vgl.viewer($('')[0]); + viewer.init(); + var renderer = viewer.renderWindow().activeRenderer(); + var renderState = new vgl.renderState(); + renderState.m_renderer = renderer; + renderState.m_context = renderer.renderWindow().context(); + var uni, i, glCounts; + for (i = 0; i < types.length; i += 1) { + glCounts = $.extend({}, vgl.mockCounts()); + uni = vgl.uniform(types[i].type, 'uniform_' + i); + uni.callGL(renderState, 'location'); + if (types[i].uniform) { + expect(vgl.mockCounts()[types[i].uniform]).toBe((glCounts[types[i].uniform] || 0) + 1); + } + } + }); + it('update', function () { + var uni, i; + for (i = 0; i < types.length; i += 1) { + uni = vgl.uniform(types[i].type, 'uniform_' + i); + expect(uni.update()).toBe(undefined); + } + }); + }); +}); + +describe('vgl.modelViewUniform', function () { + describe('Create', function () { + it('create function', function () { + var uni = vgl.modelViewUniform(); + expect(uni instanceof vgl.modelViewUniform).toBe(true); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('modelViewMatrix'); + expect(uni.type()).toBe(vgl.GL.FLOAT_MAT4); + expect(uni.get().length).toBe(16); + expect(Array.prototype.slice.call(uni.get())).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uni = vgl.modelViewUniform('sample'); + expect(uni instanceof vgl.modelViewUniform).toBe(true); + expect(uni.name()).toBe('sample'); + }); + }); + describe('Public methods', function () { + it('update', function () { + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + var renderState = {m_modelViewMatrix: data}; + var uni = vgl.modelViewUniform(); + uni.update(renderState); + expect(uni.get()).toEqual(data); + }); + }); +}); + +describe('vgl.modelViewOriginUniform', function () { + describe('Create', function () { + it('create function', function () { + var uni = vgl.modelViewOriginUniform(); + expect(uni instanceof vgl.modelViewOriginUniform).toBe(true); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('modelViewMatrix'); + expect(uni.type()).toBe(vgl.GL.FLOAT_MAT4); + expect(uni.get().length).toBe(16); + expect(Array.prototype.slice.call(uni.get())).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uni = vgl.modelViewUniform('sample', [1, 2, 3]); + expect(uni instanceof vgl.modelViewUniform).toBe(true); + expect(uni.name()).toBe('sample'); + }); + }); + describe('Public methods', function () { + it('setOrigin', function () { + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + var renderState = {m_modelViewMatrix: data}; + var uni = vgl.modelViewOriginUniform('sample', [1, 2, 3]); + uni.setOrigin([4, 5]); + uni.update(renderState); + expect(uni.get()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 42, 52, 62, 72]); + }); + it('update', function () { + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + var renderState = {m_modelViewMatrix: data}; + var uni = vgl.modelViewOriginUniform('sample', [1, 2, 3]); + uni.update(renderState); + expect(uni.get()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 51, 58, 65, 72]); + + renderState.m_modelViewAlignment = { + roundx: 4, dx: 0, + roundy: 5, dy: 0 + }; + uni.update(renderState); + expect(uni.get()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 50, 59, 65, 72]); + renderState.m_modelViewAlignment = { + roundx: 5, dx: 100, + roundy: 6, dy: 200 + }; + uni.update(renderState); + expect(uni.get()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 153, 256, 65, 72]); + }); + }); +}); + +describe('vgl.projectionUniform', function () { + describe('Create', function () { + it('create function', function () { + var uni = vgl.projectionUniform(); + expect(uni instanceof vgl.projectionUniform).toBe(true); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('projectionMatrix'); + expect(uni.type()).toBe(vgl.GL.FLOAT_MAT4); + expect(uni.get().length).toBe(16); + expect(Array.prototype.slice.call(uni.get())).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uni = vgl.projectionUniform('sample'); + expect(uni instanceof vgl.projectionUniform).toBe(true); + expect(uni.name()).toBe('sample'); + }); + }); + describe('Public methods', function () { + it('update', function () { + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + var renderState = {m_projectionMatrix: data}; + var uni = vgl.projectionUniform(); + uni.update(renderState); + expect(uni.get()).toEqual(data); + }); + }); +}); + +describe('vgl.floatUniform', function () { + describe('Create', function () { + it('create function', function () { + var uni = vgl.floatUniform(); + expect(uni instanceof vgl.floatUniform).toBe(true); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('floatUniform'); + expect(uni.type()).toBe(vgl.GL.FLOAT); + expect(uni.get().length).toBe(1); + expect(uni.get()).toEqual([1]); + uni = vgl.floatUniform('sample', 5); + expect(uni instanceof vgl.floatUniform).toBe(true); + expect(uni.name()).toBe('sample'); + expect(uni.get()).toEqual([5]); + }); + }); +}); + +describe('vgl.normalMatrixUniform', function () { + describe('Create', function () { + it('create function', function () { + var uni = vgl.normalMatrixUniform(); + expect(uni instanceof vgl.normalMatrixUniform).toBe(true); + expect(uni instanceof vgl.uniform).toBe(true); + expect(uni.name()).toBe('normalMatrix'); + expect(uni.type()).toBe(vgl.GL.FLOAT_MAT4); + expect(uni.get().length).toBe(16); + expect(Array.prototype.slice.call(uni.get())).toEqual([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uni = vgl.normalMatrixUniform('sample'); + expect(uni instanceof vgl.normalMatrixUniform).toBe(true); + expect(uni.name()).toBe('sample'); + }); + }); + describe('Public methods', function () { + it('update', function () { + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + var renderState = {m_normalMatrix: data}; + var uni = vgl.normalMatrixUniform(); + uni.update(renderState); + expect(uni.get()).toEqual(data); + }); + }); +}); diff --git a/testing/js/testUtils.js b/testing/js/testUtils.js index ce28427..0eba88b 100644 --- a/testing/js/testUtils.js +++ b/testing/js/testUtils.js @@ -185,8 +185,11 @@ function mockVGLRenderer() { texParameteri: noop('texParameteri'), uniform1iv: noop('uniform1iv'), uniform1fv: noop('uniform1fv'), + uniform2iv: noop('uniform2iv'), uniform2fv: noop('uniform2fv'), + uniform3iv: noop('uniform3iv'), uniform3fv: noop('uniform3fv'), + uniform4iv: noop('uniform4iv'), uniform4fv: noop('uniform4fv'), uniformMatrix3fv: noop('uniformMatrix3fv'), uniformMatrix4fv: noop('uniformMatrix4fv'), diff --git a/testing/test-runners/jasmine-runner.html.in b/testing/test-runners/jasmine-runner.html.in index 3029ff4..4723811 100644 --- a/testing/test-runners/jasmine-runner.html.in +++ b/testing/test-runners/jasmine-runner.html.in @@ -19,12 +19,12 @@ pointer-events: none; } - - - + + + - - + + @BLANKET_INCLUDE@ diff --git a/vgl.js b/vgl.js index ca27e5a..f6be97b 100644 --- a/vgl.js +++ b/vgl.js @@ -4,7 +4,7 @@ define('vgl', [], function () { return (root['vgl'] = factory()); }); - } else if (typeof exports === 'object') { + } else if (typeof module === 'object' && module.exports) { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. @@ -19,8 +19,7 @@ * @module vgl */ -/*global vgl: true, ogs: true, inherit*/ -/*exported vgl, inherit*/ +/* exported vgl, inherit */ ////////////////////////////////////////////////////////////////////////////// if (typeof ogs === 'undefined') { @@ -56,25 +55,27 @@ ogs.namespace = function (ns_string) { /** vgl namespace */ var vgl = ogs.namespace('gl'); +window.vgl = vgl; ////////////////////////////////////////////////////////////////////////////// /** * Convenient function to define JS inheritance - * - * @param C - * @param P */ ////////////////////////////////////////////////////////////////////////////// -function inherit(C, P) { +vgl.inherit = function (C, P) { 'use strict'; - var F = function () { - }; + var F = inherit.func(); F.prototype = P.prototype; C.prototype = new F(); - C.uber = P.prototype; C.prototype.constructor = C; -} +}; +vgl.inherit.func = function () { + 'use strict'; + return function () {}; +}; + +window.inherit = vgl.inherit; ////////////////////////////////////////////////////////////////////////////// /** @@ -87,7 +88,7 @@ function inherit(C, P) { Object.size = function (obj) { 'use strict'; - var size = 0, key = null; + var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) { size += 1; @@ -96,6 +97,15 @@ Object.size = function (obj) { return size; }; +/* Polyfill for Math.log2 */ +if (!Math.log2) { + Math.log2 = function (val) { + return Math.log(val) / Math.log(2); + }; +} + +vgl.version = '0.3.11'; + ////////////////////////////////////////////////////////////////////////////// /** * @module vgl @@ -993,9 +1003,12 @@ vgl.groupNode = function () { this.removeChild = function (childNode) { if (childNode.parent() === this) { var index = m_children.indexOf(childNode); - m_children.splice(index, 1); - this.boundsDirtyTimestamp().modified(); - return true; + if (index >= 0) { + m_children.splice(index, 1); + childNode.setParent(null); + this.boundsDirtyTimestamp().modified(); + return true; + } } }; @@ -1005,9 +1018,8 @@ vgl.groupNode = function () { */ //////////////////////////////////////////////////////////////////////////// this.removeChildren = function () { - var i; - for (i = 0; i < m_children.length; i += 1) { - this.removeChild(m_children[i]); + while (m_children.length) { + this.removeChild(m_children[0]); } this.modified(); @@ -1086,16 +1098,16 @@ vgl.groupNode = function () { this.traverseChildrenAndUpdateBounds = function (visitor) { var i; - if (this.m_parent && this.boundsDirtyTimestamp().getMTime() > + if (this.parent() && this.boundsDirtyTimestamp().getMTime() > this.computeBoundsTimestamp().getMTime()) { // Flag parents bounds dirty. - this.m_parent.boundsDirtyTimestamp.modified(); + this.parent().boundsDirtyTimestamp().modified(); } this.computeBounds(); if (visitor.mode() === visitor.TraverseAllChildren) { - for (i = 0; i < m_children.length(); i += 1) { + for (i = 0; i < m_children.length; i += 1) { m_children[i].accept(visitor); this.updateBounds(m_children[i]); } @@ -1114,8 +1126,8 @@ vgl.groupNode = function () { this.traverseChildren = function (visitor) { var i; - if (visitor.mode() === vgl.vesVisitor.TraverseAllChildren) { - for (i = 0; i < m_children.length(); i += 1) { + if (visitor.mode() === visitor.TraverseAllChildren) { + for (i = 0; i < m_children.length; i += 1) { m_children[i].accept(visitor); } } @@ -1155,7 +1167,7 @@ vgl.groupNode = function () { return; } - // Make sure that child bounds are upto date + // Make sure that child bounds are up to date child.computeBounds(); var bounds = this.bounds(), @@ -1405,11 +1417,9 @@ vgl.freezeObject = function (obj) { * * @exports freezeObject */ - var freezedObject = Object.freeze(obj); + var freezedObject = Object.freeze ? Object.freeze(obj) : undefined; if (typeof freezedObject === 'undefined') { - freezedObject = function (o) { - return o; - }; + return obj; } return freezedObject; @@ -1580,7 +1590,7 @@ vgl.geojsonReader = function () { this.readScalars = function (coordinates, geom, size_estimate, idx) { var array = null, s = null, - r = null, + r = null, g = null, b = null; @@ -1832,14 +1842,13 @@ vgl.geojsonReader = function () { vglcoords = new vgl.sourceDataP3fv(), x = null, y = null, - z = null, + z = null, thisPolyLength = coordinates[0].length, vl = 1, i = null, indices = null, vgltriangle = null; - for (i = 0; i < thisPolyLength; i += 1) { x = coordinates[0][i][0]; y = coordinates[0][i][1]; @@ -1890,7 +1899,7 @@ vgl.geojsonReader = function () { j = null, x = null, y = null, - z = null, + z = null, thisPolyLength = null, vf = null, vl = null, @@ -1898,7 +1907,6 @@ vgl.geojsonReader = function () { flipped = false, tcount = 0; - //var time1 = new Date().getTime() //var a = 0; //var b = 0; @@ -2143,8 +2151,8 @@ vgl.geojsonReader = function () { } var obj = JSON.parse(buffer), - geom = this.readGJObject(obj), - geoms = []; + geom = this.readGJObject(obj), + geoms = []; this.m_scalarFormat = 'none'; this.m_scalarRange = null; @@ -2236,7 +2244,7 @@ vgl.primitive = function () { */ //////////////////////////////////////////////////////////////////////////// this.createIndices = function (type) { - type = type; /* unused parameters */ + void type; // TODO Check for the type m_indices = new Uint16Array(); }; @@ -2526,11 +2534,11 @@ vgl.sourceData = function (arg) { m_data = [], m_name = arg.name || 'Source ' + new Date().toISOString(), - //////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// /** * Attribute data for the source */ - //////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// vglAttributeData = function () { // Number of components per group // Type of data type (GL_FLOAT etc) @@ -2668,8 +2676,8 @@ vgl.sourceData = function (arg) { var sizeInBytes = 0, keys = this.keys(), i; - for (i = 0; i < keys.length(); i += 1) { - sizeInBytes += this.numberOfComponents(keys[i]) * + for (i = 0; i < keys.length; i += 1) { + sizeInBytes += this.attributeNumberOfComponents(keys[i]) * this.sizeOfAttributeDataType(keys[i]); } @@ -2789,7 +2797,7 @@ vgl.sourceData = function (arg) { */ //////////////////////////////////////////////////////////////////////////// this.pushBack = function (vertexData) { - vertexData = vertexData; /* unused parameter */ + void vertexData; // Should be implemented by the base class }; @@ -2859,11 +2867,9 @@ vgl.sourceData = function (arg) { m_name = name; }; - return this; }; - vgl.sourceDataAnyfv = function (size, key, arg) { 'use strict'; if (!(this instanceof vgl.sourceDataAnyfv)) { @@ -3387,14 +3393,13 @@ vgl.geometryData = function () { minv = value; } } - m_bounds[ib] = minv; m_bounds[jb] = maxv; + m_bounds[ib] = minv; m_bounds[jb] = maxv; } m_computeBoundsTimestamp.modified(); } }; - //////////////////////////////////////////////////////////////////////////// /** * Returns the vertex closest to a given position @@ -3471,24 +3476,17 @@ vgl.geometryData = function () { this.getScalar = function (index) { var attr = vgl.vertexAttributeKeys.Scalar, sourceData = this.sourceData(attr), - numberOfComponents, sizeOfDataType, data, stride, offset; + sizeOfDataType, data, stride, offset; if (!sourceData) { return null; } - numberOfComponents = sourceData.attributeNumberOfComponents(attr); sizeOfDataType = sourceData.sizeOfAttributeDataType(attr); data = sourceData.data(); stride = sourceData.attributeStride(attr) / sizeOfDataType; offset = sourceData.attributeOffset(attr) / sizeOfDataType; - //console.log('index for scalar is ' + index); - //console.log('offset for scalar is ' + offset); - //console.log('stride for scalar is ' + stride); - - //console.log('have ' + data.length + ' scalars'); - if (index * stride + offset >= data.length) { console.log('access out of bounds in getScalar'); } @@ -3528,8 +3526,7 @@ vgl.mapper = function (arg) { /** @private */ arg = arg || {}; - var m_dirty = true, - m_color = [0.0, 1.0, 1.0], + var m_color = [0.0, 1.0, 1.0], m_geomData = null, m_buffers = [], m_bufferVertexAttributeMap = {}, @@ -3556,6 +3553,12 @@ vgl.mapper = function (arg) { } }; + this._cleanup = function (renderState) { + m_this.deleteVertexBufferObjects(renderState); + cleanUpDrawObjects(renderState); + m_this.modified(); + }; + //////////////////////////////////////////////////////////////////////////// /** * Create new VBO for all its geometryData sources and primitives @@ -3615,7 +3618,7 @@ vgl.mapper = function (arg) { */ //////////////////////////////////////////////////////////////////////////// function cleanUpDrawObjects(renderState) { - renderState = renderState; /* avoid unused warning */ + void renderState; m_bufferVertexAttributeMap = {}; m_buffers = []; } @@ -3636,8 +3639,6 @@ vgl.mapper = function (arg) { // Now construct the new ones. createVertexBufferObjects(renderState); - - m_dirty = false; } //////////////////////////////////////////////////////////////////////////// @@ -3659,7 +3660,7 @@ vgl.mapper = function (arg) { geomBounds = m_geomData.bounds(); this.setBounds(geomBounds[0], geomBounds[1], geomBounds[2], - geomBounds[3], geomBounds[4], geomBounds[5]) ; + geomBounds[3], geomBounds[4], geomBounds[5]); computeBoundsTimestamp.modified(); } @@ -3775,9 +3776,13 @@ vgl.mapper = function (arg) { //////////////////////////////////////////////////////////////////////////// /** * Render the mapper + * + * @param {object} renderState: the current renderering state object. + * @param {boolean} noUndoBindVertexData: if true, do not unbind vertex data. + * This may be desirable if the render function is subclassed. */ //////////////////////////////////////////////////////////////////////////// - this.render = function (renderState) { + this.render = function (renderState, noUndoBindVertexData) { if (this.getMTime() > m_glCompileTimestamp.getMTime() || renderState.m_contextChanged) { setupDrawObjects(renderState); @@ -3794,7 +3799,7 @@ vgl.mapper = function (arg) { for (i in m_bufferVertexAttributeMap) { if (m_bufferVertexAttributeMap.hasOwnProperty(i)) { m_context.bindBuffer(vgl.GL.ARRAY_BUFFER, - m_buffers[bufferIndex]); + m_buffers[bufferIndex]); for (j = 0; j < m_bufferVertexAttributeMap[i].length; j += 1) { renderState.m_material .bindVertexData(renderState, m_bufferVertexAttributeMap[i][j]); @@ -3804,10 +3809,12 @@ vgl.mapper = function (arg) { } noOfPrimitives = m_geomData.numberOfPrimitives(); - for (j = 0; j < noOfPrimitives; j += 1) { - m_context.bindBuffer(vgl.GL.ARRAY_BUFFER, m_buffers[bufferIndex]); - bufferIndex += 1; + for (j = 0; j < noOfPrimitives; j += 1, bufferIndex += 1) { primitive = m_geomData.primitive(j); + if (!primitive.numberOfIndices()) { + continue; + } + m_context.bindBuffer(vgl.GL.ARRAY_BUFFER, m_buffers[bufferIndex]); switch (primitive.primitiveType()) { case vgl.GL.POINTS: m_context.drawArrays(vgl.GL.POINTS, 0, primitive.numberOfIndices()); @@ -3825,7 +3832,31 @@ vgl.mapper = function (arg) { m_context.drawArrays(vgl.GL.TRIANGLE_STRIP, 0, primitive.numberOfIndices()); break; } - m_context.bindBuffer (vgl.GL.ARRAY_BUFFER, null); + m_context.bindBuffer(vgl.GL.ARRAY_BUFFER, null); + } + + /* If we are rendering multiple features in the same context, we must + * unbind the vertex data to make sure the next feature has a known state. + * This is optional. + */ + if (!noUndoBindVertexData) { + this.undoBindVertexData(renderState); + } + }; + + /** + * Unbind the vertex data, + */ + this.undoBindVertexData = function (renderState) { + var i, j; + + for (i in m_bufferVertexAttributeMap) { + if (m_bufferVertexAttributeMap.hasOwnProperty(i)) { + for (j = 0; j < m_bufferVertexAttributeMap[i].length; j += 1) { + renderState.m_material + .undoBindVertexData(renderState, m_bufferVertexAttributeMap[i][j]); + } + } } }; @@ -4028,7 +4059,7 @@ vgl.materialAttribute = function (type) { 'use strict'; if (!(this instanceof vgl.materialAttribute)) { - return new vgl.materialAttribute(); + return new vgl.materialAttribute(type); } vgl.graphicsObject.call(this); @@ -4070,7 +4101,7 @@ vgl.materialAttribute = function (type) { //////////////////////////////////////////////////////////////////////////// this.bindVertexData = function (renderState, key) { renderState = renderState; /* unused parameter */ - key = key /* unused parameter */; + key = key; /* unused parameter */ return false; }; @@ -4085,7 +4116,7 @@ vgl.materialAttribute = function (type) { //////////////////////////////////////////////////////////////////////////// this.undoBindVertexData = function (renderState, key) { renderState = renderState; /* unused parameter */ - key = key /* unused parameter */; + key = key; /* unused parameter */ return false; }; @@ -4265,11 +4296,10 @@ vgl.material = function () { */ //////////////////////////////////////////////////////////////////////////// this.exists = function (attr) { - if (attr.type() === vgl.materialAttribute.Texture) { - return m_textureAttributes.hasOwnProperty(attr); + if (attr.type() === vgl.materialAttributeType.Texture) { + return m_textureAttributes.hasOwnProperty(attr.textureUnit()); } - - return m_attributes.hasOwnProperty(attr); + return m_attributes.hasOwnProperty(attr.type()); }; //////////////////////////////////////////////////////////////////////////// @@ -4281,28 +4311,25 @@ vgl.material = function () { */ //////////////////////////////////////////////////////////////////////////// this.uniform = function (name) { - if (m_shaderProgram) { - return m_shaderProgram.uniform(name); - } - - return null; + return m_shaderProgram ? m_shaderProgram.uniform(name) : null; }; //////////////////////////////////////////////////////////////////////////// /** * Get material attribute - * @param attr Attribute name + * @param {number} type attribute type + * @param {number} textureUnit attribute texture unit if type is Texture. * @returns {vgl.materialAttribute} */ //////////////////////////////////////////////////////////////////////////// - this.attribute = function (name) { - if (m_attributes.hasOwnProperty(name)) { - return m_attributes[name]; + this.attribute = function (type, textureUnit) { + if (m_attributes.hasOwnProperty(type)) { + return m_attributes[type]; } - if (m_textureAttributes.hasOwnProperty(name)) { - return m_textureAttributes[name]; + if (type === vgl.materialAttributeType.Texture && m_textureAttributes.hasOwnProperty(textureUnit)) { + return m_textureAttributes[textureUnit]; } return null; @@ -4320,8 +4347,10 @@ vgl.material = function () { */ //////////////////////////////////////////////////////////////////////////// this.setAttribute = function (attr) { - if (attr.type() === vgl.materialAttributeType.Texture && - m_textureAttributes[attr.textureUnit()] !== attr) { + if (attr.type() === vgl.materialAttributeType.Texture) { + if (m_textureAttributes[attr.textureUnit()] === attr) { + return false; + } m_textureAttributes[attr.textureUnit()] = attr; m_this.modified(); return true; @@ -4392,7 +4421,7 @@ vgl.material = function () { */ //////////////////////////////////////////////////////////////////////////// this._setup = function (renderState) { - renderState = renderState; /* unused parameter */ + void renderState; /* unused parameter */ return false; }; @@ -4416,6 +4445,8 @@ vgl.material = function () { m_textureAttributes[key]._cleanup(renderState); } } + m_shaderProgram._cleanup(renderState); + m_this.modified(); }; //////////////////////////////////////////////////////////////////////////// @@ -4498,7 +4529,7 @@ vgl.material = function () { for (i in m_attributes) { if (m_attributes.hasOwnProperty(i)) { - m_attributes.undoBindVertexData(renderState, key); + m_attributes[i].undoBindVertexData(renderState, key); } } }; @@ -4637,7 +4668,6 @@ vgl.renderer = function (arg) { m_this.m_resizable = r; }; - //////////////////////////////////////////////////////////////////////////// /** * Return render window (owner) of the renderer @@ -4780,7 +4810,7 @@ vgl.renderer = function (arg) { } // Now perform sorting - sortedActors.sort(function (a, b) {return a[0] - b[0];}); + sortedActors.sort(function (a, b) { return a[0] - b[0]; }); for (i = 0; i < sortedActors.length; i += 1) { actor = sortedActors[i][1]; @@ -4817,6 +4847,7 @@ vgl.renderer = function (arg) { renSt.m_context.finish(); m_this.m_contextChanged = false; + m_this.m_lastRenderState = renSt; }; //////////////////////////////////////////////////////////////////////////// @@ -5080,10 +5111,15 @@ vgl.renderer = function (arg) { if (m_this.m_sceneRoot.children().indexOf(actor) !== -1) { /* When we remove an actor, free the VBOs of the mapper and mark the * mapper as modified; it will reallocate VBOs as necessary. */ - if (actor.mapper()) { - actor.mapper().deleteVertexBufferObjects(); - actor.mapper().modified(); + if (m_this.m_lastRenderState) { + if (actor.mapper()) { + actor.mapper()._cleanup(m_this.m_lastRenderState); + } + if (actor.material()) { + actor.material()._cleanup(m_this.m_lastRenderState); + } } + actor.modified(); m_this.m_sceneRoot.removeChild(actor); m_this.modified(); return true; @@ -5138,7 +5174,6 @@ vgl.renderer = function (arg) { winW = null, clipPt = null; - mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix); // Transform world to clipping coordinates @@ -5204,7 +5239,7 @@ vgl.renderer = function (arg) { //////////////////////////////////////////////////////////////////////////// this.focusDisplayPoint = function () { var focalPoint = m_this.m_camera.focalPoint(), - focusWorldPt = vec4.fromValues( + focusWorldPt = vec4.fromValues( focalPoint[0], focalPoint[1], focalPoint[2], 1); return m_this.worldToDisplay( @@ -5305,6 +5340,7 @@ vgl.renderer = function (arg) { } m_this.m_sceneRoot.removeChildren(); + m_this.modified(); }; return m_this; @@ -5577,8 +5613,7 @@ vgl.renderWindow = function (canvas) { } return true; - } - catch (e) { + } catch (e) { } // If we don't have a GL context, give up now @@ -5609,6 +5644,7 @@ vgl.renderWindow = function (canvas) { m_renderers[i]._cleanup(renderState); } vgl.clearCachedShaders(renderState ? renderState.m_context : null); + m_this.modified(); }; //////////////////////////////////////////////////////////////////////////// @@ -5618,7 +5654,7 @@ vgl.renderWindow = function (canvas) { //////////////////////////////////////////////////////////////////////////// this.render = function () { var i; - m_renderers.sort(function (a, b) {return a.layer() - b.layer();}); + m_renderers.sort(function (a, b) { return a.layer() - b.layer(); }); for (i = 0; i < m_renderers.length; i += 1) { m_renderers[i].render(); } @@ -5754,8 +5790,7 @@ vgl.camera = function (arg) { */ //////////////////////////////////////////////////////////////////////////// this.setViewAngleDegrees = function (a) { - m_viewAngle = (Math.PI * a) / 180.0; - this.modified(); + this.setViewAngle(Math.PI * a / 180.0); }; //////////////////////////////////////////////////////////////////////////// @@ -6258,9 +6293,9 @@ vgl.camera = function (arg) { m_position[1] = m_focalPoint[1] - d * dir[1]; m_position[2] = m_focalPoint[2] - d * dir[2]; } else { - m_position[0] = m_position[0] + d * dir[0]; - m_position[1] = m_position[1] + d * dir[1]; - m_position[2] = m_position[2] + d * dir[2]; + m_position[0] = m_position[0] + d * dir[0]; + m_position[1] = m_position[1] + d * dir[1]; + m_position[2] = m_position[2] + d * dir[2]; } this.modified(); @@ -6703,7 +6738,6 @@ vgl.trackballInteractorStyle = function () { m_currPos = {x: 0, y: 0}, m_lastPos = {x: 0, y: 0}; - ///////////////////////////////////////////////////////////////////////////// /** * Handle mouse move event @@ -6867,221 +6901,6 @@ vgl.trackballInteractorStyle = function () { }; inherit(vgl.trackballInteractorStyle, vgl.interactorStyle); -////////////////////////////////////////////////////////////////////////////// -/** - * @module vgl - */ - -/*global vgl, vec4, inherit*/ -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -/** - * Create a new instance of pvwInteractorStyle (for ParaViewWeb) - * - * @class vgl.pvwInteractorStyle - * @returns {vgl.pvwInteractorStyle} - */ -////////////////////////////////////////////////////////////////////////////// -vgl.pvwInteractorStyle = function () { - 'use strict'; - - if (!(this instanceof vgl.pvwInteractorStyle)) { - return new vgl.pvwInteractorStyle(); - } - vgl.trackballInteractorStyle.call(this); - var m_that = this, - m_leftMouseButtonDown = false, - m_rightMouseButtonDown = false, - m_middleMouseButtonDown = false, - m_width, - m_height, - m_renderer, - m_camera, - m_outsideCanvas, - m_coords, - m_currentMousePos, - m_focalPoint, - m_focusWorldPt, - m_focusDisplayPt, - m_displayPt1, - m_displayPt2, - m_worldPt1, - m_worldPt2, - m_dx, - m_dy, - m_dz, - m_zTrans, - m_mouseLastPos = { - x: 0, - y: 0 - }; - - function render() { - m_renderer.resetCameraClippingRange(); - m_that.viewer().render(); - } - - ///////////////////////////////////////////////////////////////////////////// - /** - * Handle mouse move event - * - * @param event - * @returns {boolean} - */ - ///////////////////////////////////////////////////////////////////////////// - this.handleMouseMove = function (event) { - var rens = [], i = null, secCameras = [], deltaxy = null; - m_width = m_that.viewer().renderWindow().windowSize()[0]; - m_height = m_that.viewer().renderWindow().windowSize()[1]; - m_renderer = m_that.viewer().renderWindow().activeRenderer(); - m_camera = m_renderer.camera(); - m_outsideCanvas = false; - m_coords = m_that.viewer().relMouseCoords(event); - m_currentMousePos = { - x: 0, - y: 0 - }; - - // Get secondary cameras - rens = m_that.viewer().renderWindow().renderers(); - for (i = 0; i < rens.length; i += 1) { - if (m_renderer !== rens[i]) { - secCameras.push(rens[i].camera()); - } - } - - if ((m_coords.x < 0) || (m_coords.x > m_width)) { - m_currentMousePos.x = 0; - m_outsideCanvas = true; - } else { - m_currentMousePos.x = m_coords.x; - } - if ((m_coords.y < 0) || (m_coords.y > m_height)) { - m_currentMousePos.y = 0; - m_outsideCanvas = true; - } else { - m_currentMousePos.y = m_coords.y; - } - if (m_outsideCanvas === true) { - return; - } - m_focalPoint = m_camera.focalPoint(); - m_focusWorldPt = vec4.fromValues(m_focalPoint[0], m_focalPoint[1], - m_focalPoint[2], 1); - m_focusDisplayPt = m_renderer.worldToDisplay(m_focusWorldPt, - m_camera.viewMatrix(), m_camera.projectionMatrix(), m_width, m_height); - m_displayPt1 = vec4.fromValues( - m_currentMousePos.x, m_currentMousePos.y, m_focusDisplayPt[2], 1.0); - m_displayPt2 = vec4.fromValues( - m_mouseLastPos.x, m_mouseLastPos.y, m_focusDisplayPt[2], 1.0); - m_worldPt1 = m_renderer.displayToWorld( - m_displayPt1, m_camera.viewMatrix(), m_camera.projectionMatrix(), - m_width, m_height); - m_worldPt2 = m_renderer.displayToWorld( - m_displayPt2, m_camera.viewMatrix(), m_camera.projectionMatrix(), - m_width, m_height); - - m_dx = m_worldPt1[0] - m_worldPt2[0]; - m_dy = m_worldPt1[1] - m_worldPt2[1]; - m_dz = m_worldPt1[2] - m_worldPt2[2]; - - if (m_middleMouseButtonDown) { - m_camera.pan(-m_dx, -m_dy, -m_dz); - render(); - } - if (m_leftMouseButtonDown) { - deltaxy = [(m_mouseLastPos.x - m_currentMousePos.x), - (m_mouseLastPos.y - m_currentMousePos.y)]; - m_camera.rotate(deltaxy[0], deltaxy[1]); - - // Apply rotation to all other cameras - for (i = 0; i < secCameras.length; i += 1) { - secCameras[i].rotate(deltaxy[0], deltaxy[1]); - } - - // Apply rotation to all other cameras - for (i = 0; i < rens.length; i += 1) { - rens[i].resetCameraClippingRange(); - } - render(); - } - if (m_rightMouseButtonDown) { - /// 2.0 is the speed up factor. - m_zTrans = 2.0 * (m_currentMousePos.y - m_mouseLastPos.y) / m_height; - - // Calculate zoom scale here - if (m_zTrans > 0) { - m_camera.zoom(1 - Math.abs(m_zTrans)); - } else { - m_camera.zoom(1 + Math.abs(m_zTrans)); - } - render(); - } - m_mouseLastPos.x = m_currentMousePos.x; - m_mouseLastPos.y = m_currentMousePos.y; - return false; - }; - - ///////////////////////////////////////////////////////////////////////////// - /** - * Handle mouse down event - * - * @param event - * @returns {boolean} - */ - ///////////////////////////////////////////////////////////////////////////// - this.handleMouseDown = function (event) { - if (event.button === 0) { - m_leftMouseButtonDown = true; - } - if (event.button === 1) { - m_middleMouseButtonDown = true; - } - if (event.button === 2) { - m_rightMouseButtonDown = true; - } - m_coords = m_that.viewer().relMouseCoords(event); - if (m_coords.x < 0) { - m_mouseLastPos.x = 0; - } else { - m_mouseLastPos.x = m_coords.x; - } - if (m_coords.y < 0) { - m_mouseLastPos.y = 0; - } else { - m_mouseLastPos.y = m_coords.y; - } - return false; - }; - - // @note We never get mouse up from scroll bar: See the bug report here - // http://bugs.jquery.com/ticket/8184 - ///////////////////////////////////////////////////////////////////////////// - /** - * Handle mouse up event - * - * @param event - * @returns {boolean} - */ - ///////////////////////////////////////////////////////////////////////////// - this.handleMouseUp = function (event) { - if (event.button === 0) { - m_leftMouseButtonDown = false; - } - if (event.button === 1) { - m_middleMouseButtonDown = false; - } - if (event.button === 2) { - m_rightMouseButtonDown = false; - } - return false; - }; - - return this; -}; -inherit(vgl.pvwInteractorStyle, vgl.trackballInteractorStyle); - ////////////////////////////////////////////////////////////////////////////// /** * @module vgl @@ -7613,7 +7432,6 @@ vgl.shader = function (type) { inherit(vgl.shader, vgl.object); - /* We can use the same shader multiple times if it is identical. This caches * the last N shaders and will reuse them when possible. The cache keeps the * most recently requested shader at the front. If you are doing anything more @@ -7710,7 +7528,6 @@ var getBaseUrl = (function () { return function () { return baseUrl; }; })(); - vgl.shaderProgram = function () { 'use strict'; @@ -7737,18 +7554,21 @@ vgl.shaderProgram = function () { */ ///////////////////////////////////////////////////////////////////////////// this.loadFromFile = function (type, sourceUrl) { - var shader; + var shader, success = false; $.ajax({ url: sourceUrl, type: 'GET', + dataType: 'text', async: false, success: function (result) { //console.log(result); shader = vgl.shader(type); shader.setShaderSource(result); m_this.addShader(shader); + success = true; } }); + return success; }; ///////////////////////////////////////////////////////////////////////////// @@ -7758,7 +7578,7 @@ vgl.shaderProgram = function () { */ ///////////////////////////////////////////////////////////////////////////// this.loadShader = function (type, file) { - this.loadFromFile(type, getBaseUrl() + '/shaders/' + file); + return this.loadFromFile(type, getBaseUrl() + '/shaders/' + file); }; ///////////////////////////////////////////////////////////////////////////// @@ -7799,9 +7619,9 @@ vgl.shaderProgram = function () { } var i; - for (i = 0; i < m_shaders.length; i += 1) { + for (i = m_shaders.length - 2; i >= 0; i -= 1) { if (m_shaders[i].shaderType() === shader.shaderType()) { - m_shaders.splice(m_shaders.indexOf(shader), 1); + m_shaders.splice(i, 1); } } @@ -7825,6 +7645,7 @@ vgl.shaderProgram = function () { m_uniforms.push(uniform); m_this.modified(); + return true; }; ///////////////////////////////////////////////////////////////////////////// @@ -7953,6 +7774,7 @@ vgl.shaderProgram = function () { this._cleanup = function (renderState) { m_this.deleteVertexAndFragment(renderState); m_this.deleteProgram(renderState); + m_this.modified(); }; ///////////////////////////////////////////////////////////////////////////// @@ -7961,7 +7783,10 @@ vgl.shaderProgram = function () { */ ///////////////////////////////////////////////////////////////////////////// this.deleteProgram = function (renderState) { - renderState.m_context.deleteProgram(m_programHandle); + if (m_programHandle) { + renderState.m_context.deleteProgram(m_programHandle); + } + m_programHandle = 0; }; ///////////////////////////////////////////////////////////////////////////// @@ -7972,7 +7797,9 @@ vgl.shaderProgram = function () { this.deleteVertexAndFragment = function (renderState) { var i; for (i = 0; i < m_shaders.length; i += 1) { - renderState.m_context.detachShader(m_shaders[i].shaderHandle(renderState)); + if (m_shaders[i].shaderHandle(renderState)) { + renderState.m_context.detachShader(m_programHandle, m_shaders[i].shaderHandle(renderState)); + } renderState.m_context.deleteShader(m_shaders[i].shaderHandle(renderState)); m_shaders[i].removeContext(renderState); } @@ -8211,7 +8038,7 @@ vgl.texture = function () { renderState.m_context.activeTexture(vgl.GL.TEXTURE15); break; default: - throw '[error] Texture unit ' + m_that.m_textureUnit + + throw '[error] Texture unit ' + m_that.m_textureUnit + ' is not supported'; } } @@ -8671,7 +8498,7 @@ vgl.lookupTable = function () { 1, 0.380759558, 0.320428137, 1, 0.961891484, 0.313155629, 0.265499262, 1, 0.916482116, 0.236630659, 0.209939162, 1].map( - function (x) {return x * 255;}); + function (x) { return x * 255; }); ///////////////////////////////////////////////////////////////////////////// /** @@ -8817,7 +8644,7 @@ vgl.uniform = function (type, name) { 'use strict'; if (!(this instanceof vgl.uniform)) { - return new vgl.uniform(); + return new vgl.uniform(type, name); } this.getTypeNumberOfComponents = function (type) { @@ -8900,25 +8727,9 @@ vgl.uniform = function (type, name) { */ ///////////////////////////////////////////////////////////////////////////// this.set = function (value) { - var i = 0; - if (m_dataArray.length === 16) { - for (i = 0; i < 16; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 9) { - for (i = 0; i < 9; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 4) { - for (i = 0; i < 4; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 3) { - for (i = 0; i < 3; i += 1) { - m_dataArray[i] = value[i]; - } - } else if (m_dataArray.length === 2) { - for (i = 0; i < 2; i += 1) { + var i = 0, lendata = m_dataArray.length; + if (lendata !== 1) { + for (i = 0; i < lendata; i += 1) { m_dataArray[i] = value[i]; } } else { @@ -8934,10 +8745,6 @@ vgl.uniform = function (type, name) { */ ///////////////////////////////////////////////////////////////////////////// this.callGL = function (renderState, location) { - if (this.m_numberElements < 1) { - return; - } - switch (m_type) { case vgl.GL.BOOL: case vgl.GL.INT: @@ -8946,12 +8753,24 @@ vgl.uniform = function (type, name) { case vgl.GL.FLOAT: renderState.m_context.uniform1fv(location, m_dataArray); break; + case vgl.GL.BOOL_VEC2: + case vgl.GL.INT_VEC2: + renderState.m_context.uniform2iv(location, m_dataArray); + break; case vgl.GL.FLOAT_VEC2: renderState.m_context.uniform2fv(location, m_dataArray); break; + case vgl.GL.BOOL_VEC3: + case vgl.GL.INT_VEC3: + renderState.m_context.uniform3iv(location, m_dataArray); + break; case vgl.GL.FLOAT_VEC3: renderState.m_context.uniform3fv(location, m_dataArray); break; + case vgl.GL.BOOL_VEC4: + case vgl.GL.INT_VEC4: + renderState.m_context.uniform4iv(location, m_dataArray); + break; case vgl.GL.FLOAT_VEC4: renderState.m_context.uniform4fv(location, m_dataArray); break; @@ -8977,8 +8796,8 @@ vgl.uniform = function (type, name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - renderState = renderState; /* unused parameter */ - program = program; /* unused parameter */ + void renderState; /* unused parameter */ + void program; /* unused parameter */ // Should be implemented by the derived class }; @@ -9000,7 +8819,7 @@ vgl.modelViewUniform = function (name) { return new vgl.modelViewUniform(name); } - if (name.length === 0) { + if (!name) { name = 'modelViewMatrix'; } @@ -9017,7 +8836,7 @@ vgl.modelViewUniform = function (name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ + void program; /* unused parameter */ this.set(renderState.m_modelViewMatrix); }; @@ -9042,7 +8861,7 @@ vgl.modelViewOriginUniform = function (name, origin) { return new vgl.modelViewOriginUniform(name, origin); } - if (name.length === 0) { + if (!name) { name = 'modelViewMatrix'; } origin = origin || [0, 0, 0]; @@ -9075,11 +8894,15 @@ vgl.modelViewOriginUniform = function (name, origin) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ - var view = mat4.create(); - mat4.translate(view, renderState.m_modelViewMatrix, m_origin); + void program; /* unused parameter */ + var view = renderState.m_modelViewMatrix; if (renderState.m_modelViewAlignment) { + /* adjust alignment before origin. Otherwise, a changing origin can + * affect the rounding choice and result in a 1 pixe jitter. */ var align = renderState.m_modelViewAlignment; + /* Don't modify the orignal matrix. If we are in an environment where + * you can't slice an Float32Array, switch to a regular array */ + view = view.slice ? view.slice() : Array.prototype.slice.call(view); /* view[12] and view[13] are the x and y offsets. align.round is the * units-per-pixel, and align.dx and .dy are either 0 or half the size of * a unit-per-pixel. The alignment guarantees that the texels are @@ -9087,6 +8910,7 @@ vgl.modelViewOriginUniform = function (name, origin) { view[12] = Math.round(view[12] / align.roundx) * align.roundx + align.dx; view[13] = Math.round(view[13] / align.roundy) * align.roundy + align.dy; } + view = mat4.translate(mat4.create(), view, m_origin); this.set(view); }; @@ -9110,7 +8934,7 @@ vgl.projectionUniform = function (name) { return new vgl.projectionUniform(name); } - if (name.length === 0) { + if (!name) { name = 'projectionMatrix'; } @@ -9127,7 +8951,7 @@ vgl.projectionUniform = function (name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ + void program; /* unused parameter */ this.set(renderState.m_projectionMatrix); }; @@ -9152,7 +8976,7 @@ vgl.floatUniform = function (name, value) { return new vgl.floatUniform(name, value); } - if (name.length === 0) { + if (!name) { name = 'floatUniform'; } @@ -9180,7 +9004,7 @@ vgl.normalMatrixUniform = function (name) { return new vgl.normalMatrixUniform(name); } - if (name.length === 0) { + if (!name) { name = 'normalMatrix'; } @@ -9197,7 +9021,7 @@ vgl.normalMatrixUniform = function (name) { */ ///////////////////////////////////////////////////////////////////////////// this.update = function (renderState, program) { - program = program; /* unused parameter */ + void program; /* unused parameter */ this.set(renderState.m_normalMatrix); }; @@ -9439,7 +9263,7 @@ vgl.planeSource = function () { m_geom = new vgl.geometryData(); var x = [], tc = [], v1 = [], v2 = [], - pts = [], i, j, k, ii, numPts, numPolys, + pts = [], i, j, ii, numPts, posIndex = 0, normIndex = 0, colorIndex = 0, texCoordIndex = 0, positions = [], normals = [], colors = [], texCoords = [], indices = [], tristrip = null, @@ -9460,13 +9284,12 @@ vgl.planeSource = function () { // TODO Compute center and normal // Set things up; allocate memory numPts = (m_xresolution + 1) * (m_yresolution + 1); - numPolys = m_xresolution * m_yresolution * 2; positions.length = 3 * numPts; normals.length = 3 * numPts; texCoords.length = 2 * numPts; indices.length = numPts; - for (k = 0, i = 0; i < (m_yresolution + 1); i += 1) { + for (i = 0; i < (m_yresolution + 1); i += 1) { tc[1] = i / m_yresolution; for (j = 0; j < (m_xresolution + 1); j += 1) { @@ -9719,7 +9542,6 @@ vgl.pointSource = function () { 'number of points'); } - m_geom.addPrimitive(pointsPrimitive); return m_geom; @@ -9916,17 +9738,17 @@ vgl.utils.computePowerOfTwo = function (value, pow) { vgl.utils.createTextureVertexShader = function (context) { 'use strict'; var vertexShaderSource = [ - 'attribute vec3 vertexPosition;', - 'attribute vec3 textureCoord;', - 'uniform mediump float pointSize;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'varying highp vec3 iTextureCoord;', - 'void main(void)', - '{', - 'gl_PointSize = pointSize;', - 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', - ' iTextureCoord = textureCoord;', '}'].join('\n'); + 'attribute vec3 vertexPosition;', + 'attribute vec3 textureCoord;', + 'uniform mediump float pointSize;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'varying highp vec3 iTextureCoord;', + 'void main(void)', + '{', + 'gl_PointSize = pointSize;', + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', + ' iTextureCoord = textureCoord;', '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -9944,13 +9766,13 @@ vgl.utils.createTextureVertexShader = function (context) { vgl.utils.createTextureFragmentShader = function (context) { 'use strict'; var fragmentShaderSource = [ - 'varying highp vec3 iTextureCoord;', - 'uniform sampler2D sampler2d;', - 'uniform mediump float opacity;', - 'void main(void) {', - 'gl_FragColor = vec4(texture2D(sampler2d, vec2(iTextureCoord.s, ' + + 'varying highp vec3 iTextureCoord;', + 'uniform sampler2D sampler2d;', + 'uniform mediump float opacity;', + 'void main(void) {', + 'gl_FragColor = vec4(texture2D(sampler2d, vec2(iTextureCoord.s, ' + 'iTextureCoord.t)).xyz, opacity);', - '}'].join('\n'); + '}'].join('\n'); return vgl.getCachedShader(vgl.GL.FRAGMENT_SHADER, context, fragmentShaderSource); }; @@ -9968,16 +9790,16 @@ vgl.utils.createTextureFragmentShader = function (context) { vgl.utils.createRgbaTextureFragmentShader = function (context) { 'use strict'; var fragmentShaderSource = [ - 'varying highp vec3 iTextureCoord;', - 'uniform sampler2D sampler2d;', - 'uniform mediump float opacity;', - 'void main(void) {', - ' mediump vec4 color = vec4(texture2D(sampler2d, vec2(' + + 'varying highp vec3 iTextureCoord;', + 'uniform sampler2D sampler2d;', + 'uniform mediump float opacity;', + 'void main(void) {', + ' mediump vec4 color = vec4(texture2D(sampler2d, vec2(' + 'iTextureCoord.s, iTextureCoord.t)).xyzw);', - ' color.w *= opacity;', - ' gl_FragColor = color;', - '}' - ].join('\n'); + ' color.w *= opacity;', + ' gl_FragColor = color;', + '}' + ].join('\n'); return vgl.getCachedShader(vgl.GL.FRAGMENT_SHADER, context, fragmentShaderSource); }; @@ -9995,18 +9817,18 @@ vgl.utils.createRgbaTextureFragmentShader = function (context) { vgl.utils.createVertexShader = function (context) { 'use strict'; var vertexShaderSource = [ - 'attribute vec3 vertexPosition;', - 'attribute vec3 vertexColor;', - 'uniform mediump float pointSize;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'varying mediump vec3 iVertexColor;', - 'varying highp vec3 iTextureCoord;', - 'void main(void)', - '{', - 'gl_PointSize = pointSize;', - 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', - ' iVertexColor = vertexColor;', '}'].join('\n'); + 'attribute vec3 vertexPosition;', + 'attribute vec3 vertexColor;', + 'uniform mediump float pointSize;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'varying mediump vec3 iVertexColor;', + 'varying highp vec3 iTextureCoord;', + 'void main(void)', + '{', + 'gl_PointSize = pointSize;', + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', + ' iVertexColor = vertexColor;', '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -10024,18 +9846,18 @@ vgl.utils.createVertexShader = function (context) { vgl.utils.createPointVertexShader = function (context) { 'use strict'; var vertexShaderSource = [ - 'attribute vec3 vertexPosition;', - 'attribute vec3 vertexColor;', - 'attribute float vertexSize;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'varying mediump vec3 iVertexColor;', - 'varying highp vec3 iTextureCoord;', - 'void main(void)', - '{', - 'gl_PointSize = vertexSize;', - 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', - ' iVertexColor = vertexColor;', '}'].join('\n'); + 'attribute vec3 vertexPosition;', + 'attribute vec3 vertexColor;', + 'attribute float vertexSize;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'varying mediump vec3 iVertexColor;', + 'varying highp vec3 iTextureCoord;', + 'void main(void)', + '{', + 'gl_PointSize = vertexSize;', + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', + ' iVertexColor = vertexColor;', '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -10053,15 +9875,15 @@ vgl.utils.createPointVertexShader = function (context) { vgl.utils.createVertexShaderSolidColor = function (context) { 'use strict'; var vertexShaderSource = [ - 'attribute vec3 vertexPosition;', - 'uniform mediump float pointSize;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'void main(void)', - '{', - 'gl_PointSize = pointSize;', - 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', - '}'].join('\n'); + 'attribute vec3 vertexPosition;', + 'uniform mediump float pointSize;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'void main(void)', + '{', + 'gl_PointSize = pointSize;', + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', + '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -10082,20 +9904,20 @@ vgl.utils.createVertexShaderColorMap = function (context, min, max) { min = min; /* unused parameter */ max = max; /* unused parameter */ var vertexShaderSource = [ - 'attribute vec3 vertexPosition;', - 'attribute float vertexScalar;', - 'uniform mediump float pointSize;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform float lutMin;', - 'uniform float lutMax;', - 'varying mediump float iVertexScalar;', - 'void main(void)', - '{', - 'gl_PointSize = pointSize;', - 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', - 'iVertexScalar = (vertexScalar-lutMin)/(lutMax-lutMin);', - '}'].join('\n'); + 'attribute vec3 vertexPosition;', + 'attribute float vertexScalar;', + 'uniform mediump float pointSize;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'uniform float lutMin;', + 'uniform float lutMax;', + 'varying mediump float iVertexScalar;', + 'void main(void)', + '{', + 'gl_PointSize = pointSize;', + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);', + 'iVertexScalar = (vertexScalar-lutMin)/(lutMax-lutMin);', + '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -10134,25 +9956,25 @@ vgl.utils.createFragmentShader = function (context) { vgl.utils.createPhongVertexShader = function (context) { 'use strict'; var vertexShaderSource = [ - 'attribute highp vec3 vertexPosition;', - 'attribute mediump vec3 vertexNormal;', - 'attribute mediump vec3 vertexColor;', - - 'uniform highp mat4 projectionMatrix;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 normalMatrix;', - - 'varying highp vec4 varPosition;', - 'varying mediump vec3 varNormal;', - 'varying mediump vec3 varVertexColor;', - - 'void main(void)', - '{', - 'varPosition = modelViewMatrix * vec4(vertexPosition, 1.0);', - 'gl_Position = projectionMatrix * varPosition;', - 'varNormal = vec3(normalMatrix * vec4(vertexNormal, 0.0));', - 'varVertexColor = vertexColor;', - '}'].join('\n'); + 'attribute highp vec3 vertexPosition;', + 'attribute mediump vec3 vertexNormal;', + 'attribute mediump vec3 vertexColor;', + + 'uniform highp mat4 projectionMatrix;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 normalMatrix;', + + 'varying highp vec4 varPosition;', + 'varying mediump vec3 varNormal;', + 'varying mediump vec3 varVertexColor;', + + 'void main(void)', + '{', + 'varPosition = modelViewMatrix * vec4(vertexPosition, 1.0);', + 'gl_Position = projectionMatrix * varPosition;', + 'varNormal = vec3(normalMatrix * vec4(vertexNormal, 0.0));', + 'varVertexColor = vertexColor;', + '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -10198,7 +10020,6 @@ vgl.utils.createPhongFragmentShader = function (context) { fragmentShaderSource); }; - ////////////////////////////////////////////////////////////////////////////// /** * Create a new instance of fragment shader with an assigned constant color. @@ -10212,10 +10033,10 @@ vgl.utils.createPhongFragmentShader = function (context) { vgl.utils.createFragmentShaderSolidColor = function (context, color) { 'use strict'; var fragmentShaderSource = [ - 'uniform mediump float opacity;', - 'void main(void) {', - 'gl_FragColor = vec4(' + color[0] + ',' + color[1] + ',' + color[2] + ', opacity);', - '}'].join('\n'); + 'uniform mediump float opacity;', + 'void main(void) {', + 'gl_FragColor = vec4(' + color[0] + ',' + color[1] + ',' + color[2] + ', opacity);', + '}'].join('\n'); return vgl.getCachedShader(vgl.GL.FRAGMENT_SHADER, context, fragmentShaderSource); }; @@ -10233,13 +10054,13 @@ vgl.utils.createFragmentShaderSolidColor = function (context, color) { vgl.utils.createFragmentShaderColorMap = function (context) { 'use strict'; var fragmentShaderSource = [ - 'varying mediump float iVertexScalar;', - 'uniform sampler2D sampler2d;', - 'uniform mediump float opacity;', - 'void main(void) {', - 'gl_FragColor = vec4(texture2D(sampler2d, vec2(iVertexScalar, ' + + 'varying mediump float iVertexScalar;', + 'uniform sampler2D sampler2d;', + 'uniform mediump float opacity;', + 'void main(void) {', + 'gl_FragColor = vec4(texture2D(sampler2d, vec2(iVertexScalar, ' + '0.0)).xyz, opacity);', - '}'].join('\n'); + '}'].join('\n'); return vgl.getCachedShader(vgl.GL.FRAGMENT_SHADER, context, fragmentShaderSource); }; @@ -10257,24 +10078,24 @@ vgl.utils.createFragmentShaderColorMap = function (context) { vgl.utils.createPointSpritesVertexShader = function (context) { 'use strict'; var vertexShaderSource = [ - 'attribute vec3 vertexPosition;', - 'attribute vec3 vertexColor;', - 'uniform mediump vec2 pointSize;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform float height;', - 'varying mediump vec3 iVertexColor;', - 'varying highp float iVertexScalar;', - 'void main(void)', - '{', - 'mediump float realPointSize = pointSize.y;', - 'if (pointSize.x > pointSize.y) {', - ' realPointSize = pointSize.x;}', - 'gl_PointSize = realPointSize ;', - 'iVertexScalar = vertexPosition.z;', - 'gl_Position = projectionMatrix * modelViewMatrix * ' + + 'attribute vec3 vertexPosition;', + 'attribute vec3 vertexColor;', + 'uniform mediump vec2 pointSize;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'uniform float height;', + 'varying mediump vec3 iVertexColor;', + 'varying highp float iVertexScalar;', + 'void main(void)', + '{', + 'mediump float realPointSize = pointSize.y;', + 'if (pointSize.x > pointSize.y) {', + ' realPointSize = pointSize.x;}', + 'gl_PointSize = realPointSize ;', + 'iVertexScalar = vertexPosition.z;', + 'gl_Position = projectionMatrix * modelViewMatrix * ' + 'vec4(vertexPosition.xy, height, 1.0);', - ' iVertexColor = vertexColor;', '}'].join('\n'); + ' iVertexColor = vertexColor;', '}'].join('\n'); return vgl.getCachedShader(vgl.GL.VERTEX_SHADER, context, vertexShaderSource); }; @@ -10292,34 +10113,34 @@ vgl.utils.createPointSpritesVertexShader = function (context) { vgl.utils.createPointSpritesFragmentShader = function (context) { 'use strict'; var fragmentShaderSource = [ - 'varying mediump vec3 iVertexColor;', - 'varying highp float iVertexScalar;', - 'uniform sampler2D opacityLookup;', - 'uniform highp float lutMin;', - 'uniform highp float lutMax;', - 'uniform sampler2D scalarsToColors;', - 'uniform int useScalarsToColors;', - 'uniform int useVertexColors;', - 'uniform mediump vec2 pointSize;', - 'uniform mediump float vertexColorWeight;', - 'void main(void) {', - 'mediump vec2 realTexCoord;', - 'if (pointSize.x > pointSize.y) {', - ' realTexCoord = vec2(1.0, pointSize.y/pointSize.x) * gl_PointCoord;', - '} else {', - ' realTexCoord = vec2(pointSize.x/pointSize.y, 1.0) * gl_PointCoord;', - '}', - 'highp float texOpacity = texture2D(opacityLookup, realTexCoord).w;', - 'if (useScalarsToColors == 1) {', - ' gl_FragColor = vec4(texture2D(scalarsToColors, vec2((' + + 'varying mediump vec3 iVertexColor;', + 'varying highp float iVertexScalar;', + 'uniform sampler2D opacityLookup;', + 'uniform highp float lutMin;', + 'uniform highp float lutMax;', + 'uniform sampler2D scalarsToColors;', + 'uniform int useScalarsToColors;', + 'uniform int useVertexColors;', + 'uniform mediump vec2 pointSize;', + 'uniform mediump float vertexColorWeight;', + 'void main(void) {', + 'mediump vec2 realTexCoord;', + 'if (pointSize.x > pointSize.y) {', + ' realTexCoord = vec2(1.0, pointSize.y/pointSize.x) * gl_PointCoord;', + '} else {', + ' realTexCoord = vec2(pointSize.x/pointSize.y, 1.0) * gl_PointCoord;', + '}', + 'highp float texOpacity = texture2D(opacityLookup, realTexCoord).w;', + 'if (useScalarsToColors == 1) {', + ' gl_FragColor = vec4(texture2D(scalarsToColors, vec2((' + 'iVertexScalar - lutMin)/(lutMax - lutMin), 0.0)).xyz, ' + 'texOpacity);', - '} else if (useVertexColors == 1) {', - ' gl_FragColor = vec4(iVertexColor, texOpacity);', - '} else {', - ' gl_FragColor = vec4(texture2D(opacityLookup, realTexCoord).xyz, texOpacity);', - '}}' - ].join('\n'); + '} else if (useVertexColors == 1) {', + ' gl_FragColor = vec4(iVertexColor, texOpacity);', + '} else {', + ' gl_FragColor = vec4(texture2D(opacityLookup, realTexCoord).xyz, texOpacity);', + '}}' + ].join('\n'); return vgl.getCachedShader(vgl.GL.FRAGMENT_SHADER, context, fragmentShaderSource); }; @@ -10336,17 +10157,17 @@ vgl.utils.createPointSpritesFragmentShader = function (context) { vgl.utils.createTextureMaterial = function (isRgba, origin) { 'use strict'; var mat = new vgl.material(), - blend = new vgl.blend(), - prog = new vgl.shaderProgram(), - vertexShader = vgl.utils.createTextureVertexShader(vgl.GL), - fragmentShader = null, - posVertAttr = new vgl.vertexAttribute('vertexPosition'), - texCoordVertAttr = new vgl.vertexAttribute('textureCoord'), - pointsizeUniform = new vgl.floatUniform('pointSize', 5.0), - modelViewUniform, - projectionUniform = new vgl.projectionUniform('projectionMatrix'), - samplerUniform = new vgl.uniform(vgl.GL.INT, 'sampler2d'), - opacityUniform = null; + blend = new vgl.blend(), + prog = new vgl.shaderProgram(), + vertexShader = vgl.utils.createTextureVertexShader(vgl.GL), + fragmentShader = null, + posVertAttr = new vgl.vertexAttribute('vertexPosition'), + texCoordVertAttr = new vgl.vertexAttribute('textureCoord'), + pointsizeUniform = new vgl.floatUniform('pointSize', 5.0), + modelViewUniform, + projectionUniform = new vgl.projectionUniform('projectionMatrix'), + samplerUniform = new vgl.uniform(vgl.GL.INT, 'sampler2d'), + opacityUniform = null; if (origin !== undefined) { modelViewUniform = new vgl.modelViewOriginUniform('modelViewMatrix', origin); @@ -10454,7 +10275,6 @@ vgl.utils.createPointGeometryMaterial = function (opacity) { return mat; }; - ////////////////////////////////////////////////////////////////////////////// /** * Create a new instance of geometry material with the phong shader @@ -10606,7 +10426,6 @@ vgl.utils.updateColorMappedMaterial = function (mat, lut) { return; } - var lutMin = mat.shaderProgram().uniform('lutMin'), lutMax = mat.shaderProgram().uniform('lutMax'); @@ -10999,7 +10818,7 @@ vgl.utils.createColorLegend = function (varname, lookupTable, origin, } // Create axis label - origin[0] = (positions[0] + positions[positions.length - 3] - size) * 0.5; + origin[0] = (positions[0] + positions[positions.length - 3] - size) * 0.5; origin[1] = positions[1] + axisLabelOffset; origin[2] = positions[2]; @@ -11288,7 +11107,6 @@ vgl.picker = function () { //jscs:enable disallowKeywords } - if (tymin > tmin) { tmin = tymin; } @@ -11358,51 +11176,51 @@ vgl.shapefileReader = function () { var SHP_POLYLINE = 3; this.int8 = function (data, offset) { - return data.charCodeAt (offset); + return data.charCodeAt(offset); }; /*jshint bitwise: false */ this.bint32 = function (data, offset) { return ( - ((data.charCodeAt (offset) & 0xff) << 24) + - ((data.charCodeAt (offset + 1) & 0xff) << 16) + - ((data.charCodeAt (offset + 2) & 0xff) << 8) + - (data.charCodeAt (offset + 3) & 0xff) + ((data.charCodeAt(offset) & 0xff) << 24) + + ((data.charCodeAt(offset + 1) & 0xff) << 16) + + ((data.charCodeAt(offset + 2) & 0xff) << 8) + + (data.charCodeAt(offset + 3) & 0xff) ); }; this.lint32 = function (data, offset) { return ( - ((data.charCodeAt (offset + 3) & 0xff) << 24) + - ((data.charCodeAt (offset + 2) & 0xff) << 16) + - ((data.charCodeAt (offset + 1) & 0xff) << 8) + - (data.charCodeAt (offset) & 0xff) + ((data.charCodeAt(offset + 3) & 0xff) << 24) + + ((data.charCodeAt(offset + 2) & 0xff) << 16) + + ((data.charCodeAt(offset + 1) & 0xff) << 8) + + (data.charCodeAt(offset) & 0xff) ); }; this.bint16 = function (data, offset) { return ( - ((data.charCodeAt (offset) & 0xff) << 8) + - (data.charCodeAt (offset + 1) & 0xff) + ((data.charCodeAt(offset) & 0xff) << 8) + + (data.charCodeAt(offset + 1) & 0xff) ); }; this.lint16 = function (data, offset) { return ( - ((data.charCodeAt (offset + 1) & 0xff) << 8) + - (data.charCodeAt (offset) & 0xff) + ((data.charCodeAt(offset + 1) & 0xff) << 8) + + (data.charCodeAt(offset) & 0xff) ); }; this.ldbl64 = function (data, offset) { - var b0 = data.charCodeAt (offset) & 0xff; - var b1 = data.charCodeAt (offset + 1) & 0xff; - var b2 = data.charCodeAt (offset + 2) & 0xff; - var b3 = data.charCodeAt (offset + 3) & 0xff; - var b4 = data.charCodeAt (offset + 4) & 0xff; - var b5 = data.charCodeAt (offset + 5) & 0xff; - var b6 = data.charCodeAt (offset + 6) & 0xff; - var b7 = data.charCodeAt (offset + 7) & 0xff; + var b0 = data.charCodeAt(offset) & 0xff; + var b1 = data.charCodeAt(offset + 1) & 0xff; + var b2 = data.charCodeAt(offset + 2) & 0xff; + var b3 = data.charCodeAt(offset + 3) & 0xff; + var b4 = data.charCodeAt(offset + 4) & 0xff; + var b5 = data.charCodeAt(offset + 5) & 0xff; + var b6 = data.charCodeAt(offset + 6) & 0xff; + var b7 = data.charCodeAt(offset + 7) & 0xff; var sign = 1 - 2 * (b7 >> 7); var exp = (((b7 & 0x7f) << 4) + ((b6 & 0xf0) >> 4)) - 1023; @@ -11411,24 +11229,24 @@ vgl.shapefileReader = function () { // Math.pow (2, -44) + b0 * Math.pow (2, -52); //return sign * (1 + frac) * Math.pow (2, exp); - var frac = (b6 & 0x0f) * Math.pow (2, 48) + b5 * Math.pow (2, 40) + b4 * - Math.pow (2, 32) + b3 * Math.pow (2, 24) + b2 * - Math.pow (2, 16) + b1 * Math.pow (2, 8) + b0; + var frac = (b6 & 0x0f) * Math.pow(2, 48) + b5 * Math.pow(2, 40) + b4 * + Math.pow(2, 32) + b3 * Math.pow(2, 24) + b2 * + Math.pow(2, 16) + b1 * Math.pow(2, 8) + b0; - return sign * (1 + frac * Math.pow (2, -52)) * Math.pow (2, exp); + return sign * (1 + frac * Math.pow(2, -52)) * Math.pow(2, exp); }; this.lfloat32 = function (data, offset) { - var b0 = data.charCodeAt (offset) & 0xff; - var b1 = data.charCodeAt (offset + 1) & 0xff; - var b2 = data.charCodeAt (offset + 2) & 0xff; - var b3 = data.charCodeAt (offset + 3) & 0xff; + var b0 = data.charCodeAt(offset) & 0xff; + var b1 = data.charCodeAt(offset + 1) & 0xff; + var b2 = data.charCodeAt(offset + 2) & 0xff; + var b3 = data.charCodeAt(offset + 3) & 0xff; var sign = 1 - 2 * (b3 >> 7); var exp = (((b3 & 0x7f) << 1) + ((b2 & 0xfe) >> 7)) - 127; - var frac = (b2 & 0x7f) * Math.pow (2, 16) + b1 * Math.pow (2, 8) + b0; + var frac = (b2 & 0x7f) * Math.pow(2, 16) + b1 * Math.pow(2, 8) + b0; - return sign * (1 + frac * Math.pow (2, -23)) * Math.pow (2, exp); + return sign * (1 + frac * Math.pow(2, -23)) * Math.pow(2, exp); }; /*jshint bitwise: true */ @@ -11437,14 +11255,14 @@ vgl.shapefileReader = function () { var index = offset; while (index < offset + length) { var c = data[index]; - if (c.charCodeAt (0) !== 0) { - chars.push (c); + if (c.charCodeAt(0) !== 0) { + chars.push(c); } else { break; } index += 1; } - return chars.join (''); + return chars.join(''); }; this.readHeader = function (data) { @@ -11471,33 +11289,33 @@ vgl.shapefileReader = function () { this.loadShx = function (data) { var indices = []; var appendIndex = function (offset) { - indices.push (2 * m_that.bint32(data, offset)); + indices.push(2 * m_that.bint32(data, offset)); return offset + 8; }; var offset = 100; while (offset < data.length) { - offset = appendIndex (offset); + offset = appendIndex(offset); } return indices; }; this.Shapefile = function (options) { var path = options.path; - $.ajax ({ + $.ajax({ url: path + '.shx', mimeType: 'text/plain; charset=x-user-defined', success: function (data) { var indices = this.loadShx(data); - $.ajax ({ + $.ajax({ url: path + '.shp', mimeType: 'text/plain; charset=x-user-defined', success: function (data) { - $.ajax ({ + $.ajax({ url: path + '.dbf', mimeType: 'text/plain; charset=x-user-defined', success: function (dbf_data) { - var layer = this.loadShp (data, dbf_data, indices, options); - options.success (layer); + var layer = this.loadShp(data, dbf_data, indices, options); + options.success(layer); } }); } @@ -11566,7 +11384,7 @@ vgl.shapefileReader = function () { var header_offset = FIELDS_START; var headers = []; while (header_offset < header_size - 1) { - headers.push (readHeader(header_offset)); + headers.push(readHeader(header_offset)); header_offset += HEADER_LENGTH; } @@ -11581,13 +11399,13 @@ vgl.shapefileReader = function () { // Move offset to the start of the actual data record_offset += 1; var record = {}; - for (var i = 0; i < headers.length; i += 1) { + for (var i = 0; i < headers.length; i += 1) { var header = headers[i]; var value; if (header.type === 'C') { - value = m_that.str(data, record_offset, header.length).trim (); + value = m_that.str(data, record_offset, header.length).trim(); } else if (header.type === 'N') { - value = parseFloat (m_that.str (data, record_offset, header.length)); + value = parseFloat(m_that.str(data, record_offset, header.length)); } record_offset += header.length; record[header.name] = value; @@ -11606,7 +11424,7 @@ vgl.shapefileReader = function () { for (var i = end - 1; i >= start; i -= 1) { var x = m_that.ldbl64(data, offset + 16 * i); var y = m_that.ldbl64(data, offset + 16 * i + 8); - ring.push ([x, y]); + ring.push([x, y]); } //if (ring.length <= 3) // return []; @@ -11622,13 +11440,13 @@ vgl.shapefileReader = function () { start, end, ring, rings; if (geom_type === SHP_NULL) { - console.log ('NULL Shape'); + console.log('NULL Shape'); //return offset + 12; } else if (geom_type === SHP_POINT) { var x = m_that.ldbl64(data, record_offset + 4); var y = m_that.ldbl64(data, record_offset + 12); - features.push ({ + features.push({ type: 'Point', attr: {}, geom: [[x, y]] @@ -11641,17 +11459,17 @@ vgl.shapefileReader = function () { points_start = offset + 52 + 4 * num_parts; rings = []; - for (i = 0; i < num_parts; i += 1) { + for (i = 0; i < num_parts; i += 1) { start = m_that.lint32(data, parts_start + i * 4); if (i + 1 < num_parts) { end = m_that.lint32(data, parts_start + (i + 1) * 4); } else { end = num_points; } - ring = readRing (points_start, start, end); - rings.push (ring); + ring = readRing(points_start, start, end); + rings.push(ring); } - features.push ({ + features.push({ type: 'Polygon', attr: {}, geom: [rings] @@ -11664,17 +11482,17 @@ vgl.shapefileReader = function () { points_start = offset + 52 + 4 * num_parts; rings = []; - for (i = 0; i < num_parts; i += 1) { + for (i = 0; i < num_parts; i += 1) { start = m_that.lint32(data, parts_start + i * 4); if (i + 1 < num_parts) { end = m_that.lint32(data, parts_start + (i + 1) * 4); } else { end = num_points; } - ring = readRing (points_start, start, end); - rings.push (ring); + ring = readRing(points_start, start, end); + rings.push(ring); } - features.push ({ + features.push({ type: 'Polyline', attr: {}, geom: [rings] @@ -11691,17 +11509,17 @@ vgl.shapefileReader = function () { //while (offset < length * 2) { // offset = readRecord (offset); //} - for (i = 0; i < indices.length; i += 1) { + for (i = 0; i < indices.length; i += 1) { var offset = indices[i]; - readRecord (offset); + readRecord(offset); } var layer = []; //new Layer (); - for (i = 0; i < features.length; i += 1) { + for (i = 0; i < features.length; i += 1) { var feature = features[i]; feature.attr = attr[i]; - layer.push (feature); + layer.push(feature); } return layer; }; @@ -11739,17 +11557,17 @@ vgl.vtkReader = function () { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'], - m_reverseBase64Chars = [], - m_vtkRenderedList = {}, - m_vtkObjectCount = 0, - m_vtkScene = null, - m_node = null, - END_OF_INPUT = -1, - m_base64Str = '', - m_base64Count = 0, - m_pos = 0, - m_viewer = null, - i = 0; + m_reverseBase64Chars = [], + m_vtkRenderedList = {}, + m_vtkObjectCount = 0, + m_vtkScene = null, + m_node = null, + END_OF_INPUT = -1, + m_base64Str = '', + m_base64Count = 0, + m_pos = 0, + m_viewer = null, + i = 0; //initialize the array here if not already done. if (m_reverseBase64Chars.length === 0) { @@ -11758,8 +11576,6 @@ vgl.vtkReader = function () { } } - - //////////////////////////////////////////////////////////////////////////// /** * ntos @@ -11836,9 +11652,9 @@ vgl.vtkReader = function () { /*jshint bitwise: false */ result += this.ntos((((inBuffer[0] << 2) & 0xff) | inBuffer[1] >> 4)); if (inBuffer[2] !== END_OF_INPUT) { - result += this.ntos((((inBuffer[1] << 4) & 0xff) | inBuffer[2] >> 2)); + result += this.ntos((((inBuffer[1] << 4) & 0xff) | inBuffer[2] >> 2)); if (inBuffer[3] !== END_OF_INPUT) { - result += this.ntos((((inBuffer[2] << 6) & 0xff) | inBuffer[3])); + result += this.ntos((((inBuffer[2] << 6) & 0xff) | inBuffer[3])); } else { done = true; } @@ -12032,9 +11848,9 @@ vgl.vtkReader = function () { //jshint plusplus: false for (i = 0; i < numberOfPoints; i += 1) { - p[idx++] = points[i * 3/*+0*/]; + p[idx++] = points[i * 3]; p[idx++] = points[i * 3 + 1]; - p[idx++] = points[i * 3 + 2]; + p[idx++] = points[i * 3 + 2]; } //jshint plusplus: true vglpoints.insert(p); @@ -12086,7 +11902,7 @@ vgl.vtkReader = function () { var vglpoints = null, vglcolors = null, normals = null, matrix = mat4.create(), vgltriangles = null, numberOfIndex, numberOfPoints, - points, temp, index, size, m, i, tcoord, + points, temp, index, size, m, i, pn = null, idx = 0; numberOfPoints = this.readNumber(ss); @@ -12099,10 +11915,10 @@ vgl.vtkReader = function () { normals = this.readF3Array(numberOfPoints, ss); //jshint plusplus: false for (i = 0; i < numberOfPoints; i += 1) { - pn[idx++] = points[i * 3/*+0*/]; + pn[idx++] = points[i * 3]; pn[idx++] = points[i * 3 + 1]; pn[idx++] = points[i * 3 + 2]; - pn[idx++] = normals[i * 3/*+0*/]; + pn[idx++] = normals[i * 3]; pn[idx++] = normals[i * 3 + 1]; pn[idx++] = normals[i * 3 + 2]; } @@ -12141,10 +11957,6 @@ vgl.vtkReader = function () { m = new Float32Array(temp.buffer); mat4.copy(matrix, m); - //Getting TCoord - //TODO: renderer is not doing anything with this yet - tcoord = null; - return matrix; }; @@ -12174,7 +11986,7 @@ vgl.vtkReader = function () { //jshint plusplus: false for (i = 0; i < numberOfPoints; i += 1) { indices[i] = i; - p[idx++] = points[i * 3/*+0*/]; + p[idx++] = points[i * 3]; p[idx++] = points[i * 3 + 1]; p[idx++] = points[i * 3 + 2]; } @@ -12463,7 +12275,7 @@ vgl.DataBuffers = function (initialSize) { var copyArray = function (dst, src, start, count) { if (!dst) { - console.log ('ack'); + throw 'No destination'; } if (!start) { start = 0; @@ -12490,20 +12302,28 @@ vgl.DataBuffers = function (initialSize) { size = new_size; for (var name in data) { if (data.hasOwnProperty(name)) { - var newArray = new Float32Array (new_size * data[name].len); + var newArray = new Float32Array(new_size * data[name].len); var oldArray = data[name].array; - copyArray (newArray, oldArray); + copyArray(newArray, oldArray); data[name].array = newArray; data[name].dirty = true; } } }; + /** + * Allocate a buffer with a name and a specific number of components per + * entry. If a buffer with the specified name already exists, it will be + * overwritten. + * + * @param name: the name of the buffer to create or replace. + * @param len: number of components per entry. Most be a positive integer. + */ this.create = function (name, len) { - if (!len) { + if (!len || len < 0) { throw 'Length of buffer must be a positive integer'; } - var array = new Float32Array (size * len); + var array = new Float32Array(size * len); data[name] = { array: array, len: len, @@ -12514,7 +12334,7 @@ vgl.DataBuffers = function (initialSize) { this.alloc = function (num) { if ((current + num) >= size) { - resize (current + num); + resize(current + num); } var start = current; current += num; @@ -12526,13 +12346,19 @@ vgl.DataBuffers = function (initialSize) { }; this.write = function (name, array, start, count) { - copyArray (data[name].array, array, start * data[name].len, count * data[name].len); + if (start + count > size) { + throw 'Write would exceed buffer size'; + } + copyArray(data[name].array, array, start * data[name].len, count * data[name].len); data[name].dirty = true; }; this.repeat = function (name, elem, start, count) { + if (start + count > size) { + throw 'Repeat would exceed buffer size'; + } for (var i = 0; i < count; i += 1) { - copyArray (data[name].array, elem, + copyArray(data[name].array, elem, (start + i) * data[name].len, data[name].len); } data[name].dirty = true; diff --git a/vgl.min.js b/vgl.min.js index 4dda1d5..e681e5e 100644 --- a/vgl.min.js +++ b/vgl.min.js @@ -1,5 +1,5 @@ -!function(a,b){"function"==typeof define&&define.amd?define("vgl",[],function(){return a.vgl=b()}):"object"==typeof exports?module.exports=b():a.vgl=b()}(this,function(){function a(a,b){"use strict";var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.uber=b.prototype,a.prototype.constructor=a}if("undefined"==typeof b)var b={};b.namespace=function(a){"use strict";var c,d=a.split("."),e=b;for("ogs"===d[0]&&(d=d.slice(1)),c=0;cthis.computeBoundsTimestamp().getMTime()&&this.m_parent.boundsDirtyTimestamp.modified(),this.computeBounds(),b.mode()===b.TraverseAllChildren)for(c=0;cthis.boundsDirtyTimestamp().getMTime()))for(b=0;bb;b+=1)e=2*b,f=2*b+1,d[e]c[f]&&(c[f]=d[f]);this.setBounds(c[0],c[1],c[2],c[3],c[4],c[5])}},this},a(c.groupNode,c.node),c.actor=function(){"use strict";if(!(this instanceof c.actor))return new c.actor;c.node.call(this);var a=this,b=mat4.create(),d=c.boundingObject.ReferenceFrame.Relative,e=null;return this.matrix=function(){return b},this.setMatrix=function(c){c!==b&&(b=c,a.modified())},this.referenceFrame=function(){return d},this.setReferenceFrame=function(b){return b!==d?(d=b,a.modified(),!0):!1},this.mapper=function(){return e},this.setMapper=function(b){b!==e&&(e=b,a.boundsModified())},this.accept=function(a){a=a},this.ascend=function(a){a=a},this.computeLocalToWorldMatrix=function(a,b){a=a,b=b},this.computeWorldToLocalMatrix=function(a,b){a=a,b=b},this.computeBounds=function(){if(null===e||void 0===e)return void a.resetBounds();var c,d,f,g,h=a.computeBoundsTimestamp();(a.boundsDirtyTimestamp().getMTime()>h.getMTime()||e.boundsDirtyTimestamp().getMTime()>h.getMTime())&&(e.computeBounds(),c=e.bounds(),d=[c[0],c[2],c[4]],f=[c[1],c[3],c[5]],vec3.transformMat4(d,d,b),vec3.transformMat4(f,f,b),g=[d[0]>f[0]?f[0]:d[0],d[0]>f[0]?d[0]:f[0],d[1]>f[1]?f[1]:d[1],d[1]>f[1]?d[1]:f[1],d[2]>f[2]?f[2]:d[2],d[2]>f[2]?d[2]:f[2]],a.setBounds(g[0],g[1],g[2],g[3],g[4],g[5]),h.modified())},a},a(c.actor,c.node),c.freezeObject=function(a){"use strict";var b=Object.freeze(a);return"undefined"==typeof b&&(b=function(a){return a}),b},c.defaultValue=function(a,b){"use strict";return"undefined"!=typeof a?a:b},c.defaultValue.EMPTY_OBJECT=c.freezeObject({}),c.graphicsObject=function(a){"use strict";if(a=a,!(this instanceof c.graphicsObject))return new c.graphicsObject;c.object.call(this);var b=this;return this._setup=function(a){return a=a,!1},this._cleanup=function(a){return a=a,!1},this.bind=function(a){return a=a,!1},this.undoBind=function(a){return a=a,!1},this.render=function(a){return a=a,!1},this.remove=function(a){b._cleanup(a)},b},a(c.graphicsObject,c.object),c.geojsonReader=function(){"use strict";return this instanceof c.geojsonReader?(this.readScalars=function(a,b,d,e){var f=null,g=null,h=null,i=null,j=null;"values"===this.m_scalarFormat&&4===a.length?(g=a[3],f=b.sourceData(c.vertexAttributeKeys.Scalar),f||(f=new c.sourceDataSf,this.m_scalarRange&&f.setScalarRange(this.m_scalarRange[0],this.m_scalarRange[1]),void 0!==d&&(f.data().length=d),b.addSource(f)),void 0===d?f.pushBack(g):f.insertAt(e,g)):"rgb"===this.m_scalarFormat&&6===a.length&&(f=b.sourceData(c.vertexAttributeKeys.Color),f||(f=new c.sourceDataC3fv,void 0!==d&&(f.length=3*d),b.addSource(f)),h=a[3],i=a[4],j=a[5],void 0===d?f.pushBack([h,i,j]):f.insertAt(e,[h,i,j]))},this.readPoint=function(a){var b=new c.geometryData,d=new c.points,e=new c.sourceDataP3fv,f=new Uint16Array(1),g=null,h=null,i=null,j=null;for(b.addSource(e),j=0;1>j;j+=1)f[j]=j,g=a[0],h=a[1],i=0,a.length>2&&(i=a[2]),e.pushBack([g,h,i]),this.readScalars(a,b);return d.setIndices(f),b.addPrimitive(d),b.setName("aPoint"),b},this.readMultiPoint=function(a){var b,d=new c.geometryData,e=new c.points,f=new c.sourceDataP3fv,g=new Uint16Array(a.length),h=0,i=a.length,j=null,k=null,l=null;for(f.data().length=3*i,b=0;b2&&(l=a[b][2]),f.insertAt(h,[j,k,l]),this.readScalars(a[b],d,i,h),h+=1;return e.setIndices(g),d.addPrimitive(e),d.addSource(f),d.setName("manyPoints"),d},this.readLineString=function(a){var b=new c.geometryData,d=new c.lineStrip,e=new c.sourceDataP3fv,f=[],g=null,h=null,i=null,j=null;for(d.setIndicesPerPrimitive(a.length),g=0;g2&&(j=a[g][2]),e.pushBack([h,i,j]),this.readScalars(a[g],b);return d.setIndices(f),b.addPrimitive(d),b.addSource(e),b.setName("aLineString"),b},this.readMultiLineString=function(a){var b=new c.geometryData,d=new c.sourceDataP3fv,e=0,f=2*a.length,g=null,h=null,i=null,j=null,k=null,l=null,m=null,n=null;for(d.data().length=3*f,h=0;hg;g+=1)l.push(e),i=a[h][g][0],j=a[h][g][1],k=0,a[h][g].length>2&&(k=a[h][g][2]),d.insertAt(e,[i,j,k]),this.readScalars(a[h][g],b,2*f,e),e+=1;m.setIndices(l),b.addPrimitive(m)}return b.setName("aMultiLineString"),b.addSource(d),b},this.readPolygon=function(a){var b=new c.geometryData,d=new c.sourceDataP3fv,e=null,f=null,g=null,h=a[0].length,i=1,j=null,k=null,l=null;for(j=0;h>j;j+=1)e=a[0][j][0],f=a[0][j][1],g=0,a[0][j].length>2&&(g=a[0][j][2]),d.pushBack([e,f,g]),this.readScalars(a[0][j],b),j>1&&(k=new Uint16Array([0,i,j]),l=new c.triangles,l.setIndices(k),b.addPrimitive(l),i=j);return b.setName("POLY"),b.addSource(d),b},this.readMultiPolygon=function(a){var b=new c.geometryData,d=new c.sourceDataP3fv,e=0,f=a.length,g=0,h=3*f,i=new c.triangles,j=[],k=null,l=null,m=null,n=null,o=null,p=null,q=null,r=null,s=null,t=!1,u=0;for(d.data().length=3*f,l=0;f>l;l+=1)for(p=a[l][0].length,q=e,r=e+1,s=[!1,!1,!1],k=0;p>k;k+=1)m=a[l][0][k][0],n=a[l][0][k][1],o=0,a[l][0][k].length>2&&(o=a[l][0][k][2]),t=!1,m>180&&(t=!0,m-=360),0===k?s[0]=t:s[1+(k-1)%2]=t,d.insertAt(g,[m,n,o]),this.readScalars(a[l][0][k],b,h,g),g+=1,k>1&&(s[0]===s[1]&&s[1]===s[2]&&(j[3*u+0]=q,j[3*u+1]=r,j[3*u+2]=e,u+=1),r=e),e+=1;return i.setIndices(j),b.addPrimitive(i),b.setName("aMultiPoly"),b.addSource(d),b},this.readGJObjectInt=function(a){if(!a.hasOwnProperty("type"))return null;a.properties&&a.properties.ScalarFormat&&"values"===a.properties.ScalarFormat&&(this.m_scalarFormat="values",a.properties.ScalarRange&&(this.m_scalarRange=a.properties.ScalarRange)),a.properties&&a.properties.ScalarFormat&&"rgb"===a.properties.ScalarFormat&&(this.m_scalarFormat="rgb");var b,c=a.type,d=null,e=null,f=null;switch(c){case"Point":b=this.readPoint(a.coordinates);break;case"MultiPoint":b=this.readMultiPoint(a.coordinates);break;case"LineString":b=this.readLineString(a.coordinates);break;case"MultiLineString":b=this.readMultiLineString(a.coordinates);break;case"Polygon":b=this.readPolygon(a.coordinates);break;case"MultiPolygon":b=this.readMultiPolygon(a.coordinates);break;case"GeometryCollection":for(e=[],f=0;fd)&&(d=a),(null===b||b>a)&&(b=a),this.data()[this.data().length]=a},this.insertAt=function(a,c){(null===d||c>d)&&(d=c),(null===b||b>c)&&(b=c),this.data()[a]=c},this.scalarRange=function(){return null===e||null===f?[b,d]:[e,f]},this.setScalarRange=function(a,b){e=a,f=b},this},a(c.sourceDataSf,c.sourceData),c.sourceDataDf=function(a){"use strict";return this instanceof c.sourceDataDf?(c.sourceData.call(this,a),this.addAttribute(c.vertexAttributeKeys.Scalar,c.GL.FLOAT,4,0,4,1,!1),this.pushBack=function(a){this.data()[this.data().length]=a},this.insertAt=function(a,b){this.data()[a]=b},this):new c.sourceDataDf(a)},a(c.sourceDataDf,c.sourceData),c.geometryData=function(){"use strict";if(!(this instanceof c.geometryData))return new c.geometryData;c.data.call(this);var a="",b=[],d=[],e=[0,0,0,0,0,0],f=c.timestamp(),g=c.timestamp();return this.type=function(){return c.data.geometry},this.name=function(){return a},this.setName=function(b){a=b},this.addSource=function(a,b){return void 0!==b&&a.setName(b),-1===d.indexOf(a)?(d.push(a),a.hasKey(c.vertexAttributeKeys.Position)&&g.modified(),!0):!1},this.source=function(a){return af.getMTime()&&this.computeBounds(),e},this.boundsDirty=function(a){return a&&g.modified(),g.getMTime()>f.getMTime()},this.resetBounds=function(){e[0]=0,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=0},this.setBounds=function(a,b,c,d,g,h){return e[0]=a,e[1]=b,e[2]=c,e[3]=d,e[4]=g,e[5]=h,f.modified(),!0},this.computeBounds=function(){if(g.getMTime()>f.getMTime()){var a,b,d,h,i,j,k=c.vertexAttributeKeys.Position,l=this.sourceData(k),m=l.data(),n=l.attributeNumberOfComponents(k),o=l.attributeStride(k),p=l.attributeOffset(k),q=l.sizeOfAttributeDataType(k),r=m.length,s=null;for(o/=q,p/=q,this.resetBounds(),a=0;n>a;a+=1){for(b=2*a,d=2*a+1,h=i=r?e[d]=m[p+a]:0,j=p+o+a;r>j;j+=o)s=m[j],s>h&&(h=s),i>s&&(i=s);e[b]=i,e[d]=h}f.modified()}},this.findClosestVertex=function(a){var b,d,e,f,g,h,i,j=c.vertexAttributeKeys.Position,k=this.sourceData(j),l=k.sizeOfAttributeDataType(j),m=k.attributeNumberOfComponents(j),n=k.data(),o=k.attributeStride(j)/l,p=k.attributeOffset(j)/l,q=Number.MAX_VALUE,r=null;for(3!==m&&console.log("[warning] Find closest vertex assumes threecomponent vertex "),a.z||(a={x:a.x,y:a.y,z:0}),b=p,i=0;bh&&(q=h,r=i);return r},this.getPosition=function(a){var b=c.vertexAttributeKeys.Position,d=this.sourceData(b),e=d.sizeOfAttributeDataType(b),f=d.attributeNumberOfComponents(b),g=d.data(),h=d.attributeStride(b)/e,i=d.attributeOffset(b)/e;return 3!==f&&console.log("[warning] getPosition assumes three component data"),[g[i+a*h],g[i+a*h+1],g[i+a*h+2]]},this.getScalar=function(a){var b,d,e,f,g,h=c.vertexAttributeKeys.Scalar,i=this.sourceData(h);return i?(b=i.attributeNumberOfComponents(h),d=i.sizeOfAttributeDataType(h),e=i.data(),f=i.attributeStride(h)/d,g=i.attributeOffset(h)/d,a*f+g>=e.length&&console.log("access out of bounds in getScalar"),e[a*f+g]):null},this},a(c.geometryData,c.data),c.mapper=function(a){"use strict";function b(a){if(h){a&&(m=a.m_context);var b,d,e,f,g,n,o,p=h.numberOfSources(),q=null;for(b=0;p>b;b+=1){for(q=m.createBuffer(),m.bindBuffer(c.GL.ARRAY_BUFFER,q),o=h.source(b).data(),o instanceof Float32Array||(o=new Float32Array(o)),m.bufferData(c.GL.ARRAY_BUFFER,o,k?c.GL.DYNAMIC_DRAW:c.GL.STATIC_DRAW),f=h.source(b).keys(),g=[],d=0;de;e+=1)q=m.createBuffer(),m.bindBuffer(c.GL.ARRAY_BUFFER,q),m.bufferData(c.GL.ARRAY_BUFFER,h.primitive(e).indices(),c.GL.STATIC_DRAW),i[b]=q,b+=1;l.modified()}}function d(a){a=a,j={},i=[]}function e(a){n.deleteVertexBufferObjects(a),d(a),b(a),f=!1}if(!(this instanceof c.mapper))return new c.mapper(a);c.boundingObject.call(this),a=a||{};var f=!0,g=[0,1,1],h=null,i=[],j={},k=void 0===a.dynamicDraw?!1:a.dynamicDraw,l=c.timestamp(),m=null,n=this;return this.deleteVertexBufferObjects=function(a){var b,c=m;if(a&&(c=a.m_context),c)for(b=0;ba.getMTime()&&(c=h.bounds(),this.setBounds(c[0],c[1],c[2],c[3],c[4],c[5]),a.modified())},this.color=function(){return g},this.setColor=function(a,b,c){g[0]=a,g[1]=b,g[2]=c,this.modified()},this.geometryData=function(){return h},this.setGeometryData=function(a){h!==a&&(h=a,this.modified(),this.boundsDirtyTimestamp().modified())},this.updateSourceBuffer=function(a,b,d){if(d&&(m=d.m_context),!m)return!1;for(var e=-1,f=0;fe||e>=i.length?!1:(b||(b=h.source(f).dataToFloat32Array()),m.bindBuffer(c.GL.ARRAY_BUFFER,i[e]),b instanceof Float32Array?m.bufferSubData(c.GL.ARRAY_BUFFER,0,b):m.bufferSubData(c.GL.ARRAY_BUFFER,0,new Float32Array(b)),!0)},this.getSourceBuffer=function(a){var b=h.sourceByName(a);return b?b.dataToFloat32Array():new Float32Array},this.render=function(a){(this.getMTime()>l.getMTime()||a.m_contextChanged)&&e(a),m=a.m_context,m.vertexAttrib3fv(c.vertexAttributeKeys.Color,this.color());var b,d=0,f=0,g=null,k=null;for(b in j)if(j.hasOwnProperty(b)){for(m.bindBuffer(c.GL.ARRAY_BUFFER,i[d]), -f=0;ff;f+=1){switch(m.bindBuffer(c.GL.ARRAY_BUFFER,i[d]),d+=1,k=h.primitive(f),k.primitiveType()){case c.GL.POINTS:m.drawArrays(c.GL.POINTS,0,k.numberOfIndices());break;case c.GL.LINES:m.drawArrays(c.GL.LINES,0,k.numberOfIndices());break;case c.GL.LINE_STRIP:m.drawArrays(c.GL.LINE_STRIP,0,k.numberOfIndices());break;case c.GL.TRIANGLES:m.drawArrays(c.GL.TRIANGLES,0,k.numberOfIndices());break;case c.GL.TRIANGLE_STRIP:m.drawArrays(c.GL.TRIANGLE_STRIP,0,k.numberOfIndices())}m.bindBuffer(c.GL.ARRAY_BUFFER,null)}},this},a(c.mapper,c.boundingObject),c.groupMapper=function(){"use strict";if(!(this instanceof c.groupMapper))return new c.groupMapper;c.mapper.call(this);var a=c.timestamp(),b=[],d=[];return this.geometryData=function(a){return void 0!==a&&a0?d[0]:null},this.setGeometryData=function(a){(1!==d.length||d[0]!==a)&&(d=[],d.push(a),this.modified())},this.geometryDataArray=function(){return d},this.setGeometryDataArray=function(a){if(a instanceof Array){if(d!==a)return d=[],d=a,this.modified(),!0}else console.log("[error] Requies array of geometry data");return!1},this.computeBounds=function(){if(null===d||void 0===d)return void this.resetBounds();var a=this.computeBoundsTimestamp(),b=this.boundsDirtyTimestamp(),c=this.bounds(),e=null,f=null;if(b.getMTime()>a.getMTime()){for(f=0;fe[0]&&(c[0]=e[0]),c[1]e[2]&&(c[2]=e[2]),c[3]e[4]&&(c[4]=e[4]),c[5]a.getMTime()){for(f=0;f0&&b.m_resetScene&&(b.resetCamera(),b.m_resetScene=!1),a=0;a=0&&g.push([f.material().binNumber(),f]);for(g.sort(function(a,b){return a[0]-b[0]}),a=0;ae[1]?e[0]>e[2]?e[0]/2:e[2]/2:e[1]>e[2]?e[1]/2:e[2]/2,h=g>=1?2*Math.atan(Math.tan(.5*h)/g):2*Math.atan(Math.tan(.5*h)*g),i=f/Math.sin(.5*h),j=b.m_camera.viewUpDirection(),Math.abs(vec3.dot(j,a))>.999&&b.m_camera.setViewUpDirection(-j[2],j[0],j[1]),b.m_camera.setFocalPoint(d[0],d[1],d[2]),b.m_camera.setPosition(d[0]+i*-a[0],d[1]+i*-a[1],d[2]+i*-a[2]),b.resetCameraClippingRange(c)},this.hasValidBounds=function(a){return a[0]===Number.MAX_VALUE||a[1]===-Number.MAX_VALUE||a[2]===Number.MAX_VALUE||a[3]===-Number.MAX_VALUE||a[4]===Number.MAX_VALUE||a[5]===-Number.MAX_VALUE?!1:!0},this.resetCameraClippingRange=function(a){if("undefined"==typeof a&&(b.m_camera.computeBounds(),a=b.m_camera.bounds()),b.hasValidBounds(a)){var c=b.m_camera.viewPlaneNormal(),d=b.m_camera.position(),e=-c[0],f=-c[1],g=-c[2],h=-(e*d[0]+f*d[1]+g*d[2]),i=vec2.create(),j=null,k=null,l=null,m=null;if(b.m_resetClippingRange){for(i[0]=e*a[0]+f*a[2]+g*a[4]+h,i[1]=1e-18,m=0;2>m;m+=1)for(l=0;2>l;l+=1)for(k=0;2>k;k+=1)j=e*a[k]+f*a[2+l]+g*a[4+m]+h,i[0]=ji[1]?j:i[1];i[0]<0&&(i[0]=0),i[0]=.99*i[0]-.5*(i[1]-i[0]),i[1]=1.01*i[1]+.5*(i[1]-i[0]),i[0]=i[0]>=i[1]?.01*i[1]:i[0],b.m_nearClippingPlaneTolerance||(b.m_nearClippingPlaneTolerance=.01,b.m_depthBits&&b.m_depthBits>16&&(b.m_nearClippingPlaneTolerance=.001)),i[0]a||0>c||0>=d||0>=e)return void console.log("[error] Invalid position and resize values",a,c,d,e);if(b.m_resizable&&(b.m_width=d,b.m_height=e,b.m_camera.setViewAspect(d/e),b.m_camera.setParallelExtents({width:d,height:e}),b.modified()),b.m_renderPasses)for(f=0;ff||0===j[b].width()||j[b].height()>g||0===j[b].height())&&j[b].resize(d,e,f,g);return!0}catch(c){}return k||console("[ERROR] Unable to initialize WebGL. Your browser may not support it."),!1},this.context=function(){return k},this._cleanup=function(a){var b;for(b=0;bt?(g.x=0,a=!0):g.x=x.x,x.y<0||x.y>u?(g.y=0,a=!0):g.y=x.y,a!==!0?(i=w.focalPoint(),k=vec4.fromValues(i[0],i[1],i[2],1),j=v.worldToDisplay(k,w.viewMatrix(),w.projectionMatrix(),t,u),l=vec4.fromValues(g.x,g.y,j[2],1),m=vec4.fromValues(h.x,h.y,j[2],1),n=v.displayToWorld(l,w.viewMatrix(),w.projectionMatrix(),t,u),o=v.displayToWorld(m,w.viewMatrix(),w.projectionMatrix(),t,u),p=n[0]-o[0],q=n[1]-o[1],r=n[2]-o[2],f&&(w.pan(-p,-q,-r),b.viewer().render()),d&&(w.rotate(h.x-g.x,h.y-g.y),v.resetCameraClippingRange(),b.viewer().render()),e&&(s=2*(g.y-h.y)/u,s>0?w.zoom(1-Math.abs(s)):w.zoom(1+Math.abs(s)),v.resetCameraClippingRange(),b.viewer().render()),h.x=g.x,h.y=g.y,!1):void 0},this.handleMouseDown=function(a){var c;return 0===a.button&&(d=!0),1===a.button&&(f=!0),2===a.button&&(e=!0),c=b.viewer().relMouseCoords(a),c.x<0?h.x=0:h.x=c.x,c.y<0?h.y=0:h.y=c.y,!1},this.handleMouseUp=function(a){return 0===a.button&&(d=!1),1===a.button&&(f=!1),2===a.button&&(e=!1),!1},this.handleMouseWheel=function(a){var c=b.viewer().renderWindow().activeRenderer(),d=c.camera();return a.originalEvent.wheelDelta<0?d.zoom(.9):d.zoom(1.1),c.resetCameraClippingRange(),b.viewer().render(),!0},this},a(c.trackballInteractorStyle,c.interactorStyle),c.pvwInteractorStyle=function(){"use strict";function a(){e.resetCameraClippingRange(),u.viewer().render()}if(!(this instanceof c.pvwInteractorStyle))return new c.pvwInteractorStyle;c.trackballInteractorStyle.call(this);var b,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=this,v=!1,w=!1,x=!1,y={x:0,y:0};return this.handleMouseMove=function(c){var z=[],A=null,B=[],C=null;for(b=u.viewer().renderWindow().windowSize()[0],d=u.viewer().renderWindow().windowSize()[1],e=u.viewer().renderWindow().activeRenderer(),f=e.camera(),g=!1,h=u.viewer().relMouseCoords(c),i={x:0,y:0},z=u.viewer().renderWindow().renderers(),A=0;Ab?(i.x=0,g=!0):i.x=h.x,h.y<0||h.y>d?(i.y=0,g=!0):i.y=h.y,g!==!0){if(j=f.focalPoint(),k=vec4.fromValues(j[0],j[1],j[2],1),l=e.worldToDisplay(k,f.viewMatrix(),f.projectionMatrix(),b,d),m=vec4.fromValues(i.x,i.y,l[2],1),n=vec4.fromValues(y.x,y.y,l[2],1),o=e.displayToWorld(m,f.viewMatrix(),f.projectionMatrix(),b,d),p=e.displayToWorld(n,f.viewMatrix(),f.projectionMatrix(),b,d),q=o[0]-p[0],r=o[1]-p[1],s=o[2]-p[2],x&&(f.pan(-q,-r,-s),a()),v){for(C=[y.x-i.x,y.y-i.y],f.rotate(C[0],C[1]),A=0;A0?f.zoom(1-Math.abs(t)):f.zoom(1+Math.abs(t)),a()),y.x=i.x,y.y=i.y,!1}},this.handleMouseDown=function(a){return 0===a.button&&(v=!0),1===a.button&&(x=!0),2===a.button&&(w=!0),h=u.viewer().relMouseCoords(a),h.x<0?y.x=0:y.x=h.x,h.y<0?y.y=0:y.y=h.y,!1},this.handleMouseUp=function(a){return 0===a.button&&(v=!1),1===a.button&&(x=!1),2===a.button&&(w=!1),!1},this},a(c.pvwInteractorStyle,c.trackballInteractorStyle),c.viewer=function(a,b){"use strict";if(!(this instanceof c.viewer))return new c.viewer(a,b);c.object.call(this);var d=this,e=a,f=!0,g=null,h=c.renderer(b),i=c.renderWindow(e);return this.canvas=function(){return e},this.renderWindow=function(){return i},this.init=function(){null!==i?i._setup():console.log("[ERROR] No render window attached")},this.exit=function(a){null!==i?i._cleanup(a):console.log("[ERROR] No render window attached")},this.interactorStyle=function(){return g},this.setInteractorStyle=function(a){a!==g&&(g=a,g.setViewer(this),this.modified())},this.handleMouseDown=function(a){if(f===!0){var b=$.event.fix(a||window.event);2===a.button&&b.preventDefault(),b.state="down",b.type=c.event.mousePress,$(d).trigger(b)}return!0},this.handleMouseUp=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.state="up",b.type=c.event.mouseRelease,$(d).trigger(b)}return!0},this.handleMouseMove=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.mouseMove,$(d).trigger(b)}return!0},this.handleMouseWheel=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.mouseWheel,$(d).trigger(b)}return!0},this.handleMouseOut=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.mouseOut,$(d).trigger(b)}return!0},this.handleKeyPress=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.keyPress,$(d).trigger(b)}return!0},this.handleContextMenu=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.contextMenu,$(d).trigger(b)}return!1},this.handleClick=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.click,$(d).trigger(b)}return!1},this.handleDoubleClick=function(a){if(f===!0){var b=$.event.fix(a||window.event);b.preventDefault(),b.type=c.event.dblClick,$(d).trigger(b)}return!1},this.relMouseCoords=function(a){if(void 0===a.pageX||void 0===a.pageY)throw"Missing attributes pageX and pageY on the event";var b=0,c=0,d=0,f=0,g=e;do b+=g.offsetLeft-g.scrollLeft,c+=g.offsetTop-g.scrollTop,g=g.offsetParent;while(g);return d=a.pageX-b,f=a.pageY-c,{x:d,y:f}},this.render=function(){i.render()},this.bindEventHandlers=function(){$(e).on("mousedown",this.handleMouseDown),$(e).on("mouseup",this.handleMouseUp),$(e).on("mousemove",this.handleMouseMove),$(e).on("mousewheel",this.handleMouseWheel),$(e).on("contextmenu",this.handleContextMenu)},this.unbindEventHandlers=function(){$(e).off("mousedown",this.handleMouseDown),$(e).off("mouseup",this.handleMouseUp),$(e).off("mousemove",this.handleMouseMove),$(e).off("mousewheel",this.handleMouseWheel),$(e).off("contextmenu",this.handleContextMenu)},this._init=function(){this.bindEventHandlers(),i.addRenderer(h)},this._init(),this},a(c.viewer,c.object),c.shader=function(a){"use strict";if(!(this instanceof c.shader))return new c.shader(a);c.object.call(this);var b=[],d=a,e="";this._getContextEntry=function(a){var d,e,f=a.m_context;for(d=0;d=b&&a.splice(b,a.length-b),h},c.clearCachedShaders=function(b){for(var c=a.length-1;c>=0;c-=1)(null===b||void 0===b||a[c].context===b)&&a.splice(c,1)}}();var e=function(){"use strict";var a=".",b=document.getElementsByTagName("script");if(b.length>0){var c=b.length-1,d=b[c];c=d.src.lastIndexOf("/"),a=d.src.substring(0,c)}return function(){return a}}();return c.shaderProgram=function(){"use strict";if(!(this instanceof c.shaderProgram))return new c.shaderProgram;c.materialAttribute.call(this,c.materialAttributeType.ShaderProgram);var a=this,b=0,d=c.timestamp(),f=c.timestamp(),g=[],h=[],i={},j={},k={};return this.loadFromFile=function(b,d){var e;$.ajax({url:d,type:"GET",async:!1,success:function(d){e=c.shader(b),e.setShaderSource(d),a.addShader(e)}})},this.loadShader=function(a,b){this.loadFromFile(a,e()+"/shaders/"+b)},this.queryUniformLocation=function(a,c){return a.m_context.getUniformLocation(b,c)},this.queryAttributeLocation=function(a,c){return a.m_context.getAttribLocation(b,c)},this.addShader=function(b){if(g.indexOf(b)>-1)return!1;var c;for(c=0;c-1?!1:(h.push(b),void a.modified())},this.addVertexAttribute=function(b,c){i[c]=b,a.modified()},this.uniformLocation=function(a){return j[a]},this.attributeLocation=function(a){return k[a]},this.uniform=function(a){var b;for(b=0;b=this.getMTime())){for(a._setup(c),e=0;eb.getMTime()&&this.setup(d),a(d),d.m_context.bindTexture(c.GL.TEXTURE_2D,this.m_textureHandle)},this.undoBind=function(a){a.m_context.bindTexture(c.GL.TEXTURE_2D,null)},this.image=function(){return this.m_image},this.setImage=function(a){return null!==a?(this.m_image=a,this.updateDimensions(),this.modified(),!0):!1},this.nearestPixel=function(){return this.m_nearestPixel},this.setNearestPixel=function(a){return a=a?!0:!1,a!==this.m_nearestPixel?(this.m_nearestPixel=a,this.modified(),!0):!1},this.textureUnit=function(){return this.m_textureUnit},this.setTextureUnit=function(a){return this.m_textureUnit===a?!1:(this.m_textureUnit=a,this.modified(),!0)},this.width=function(){return this.m_width},this.setWidth=function(a){return d.m_width!==a?(d.m_width=a,d.modified(),!0):!1},this.height=function(){return d.m_height},this.setHeight=function(a){return d.m_height!==a?(d.m_height=a,d.modified(),!0):!1},this.depth=function(){return this.m_depth},this.setDepth=function(a){return null===this.m_image?!1:(this.m_depth=a,this.modified(),!0)},this.textureHandle=function(){return this.m_textureHandle},this.internalFormat=function(){return this.m_internalFormat},this.setInternalFormat=function(a){return this.m_internalFormat!==a?(this.m_internalFormat=a,this.modified(),!0):!1},this.pixelFormat=function(){return this.m_pixelFormat},this.setPixelFormat=function(a){return null===this.m_image?!1:(this.m_pixelFormat=a,this.modified(),!0)},this.pixelDataType=function(){return this.m_pixelDataType},this.setPixelDataType=function(a){return null===this.m_image?!1:(this.m_pixelDataType=a,this.modified(),!0)},this.computeInternalFormatUsingImage=function(){this.m_internalFormat=c.GL.RGBA,this.m_pixelFormat=c.GL.RGBA,this.m_pixelDataType=c.GL.UNSIGNED_BYTE},this.updateDimensions=function(){null!==this.m_image&&(this.m_width=this.m_image.width,this.m_height=this.m_image.height,this.m_depth=0)},this},a(c.texture,c.materialAttribute),c.lookupTable=function(){"use strict";if(!(this instanceof c.lookupTable))return new c.lookupTable;c.texture.call(this);var a=c.timestamp(),b=[0,0];return this.m_colorTable=[.07514311,.468049805,1,1,.247872569,.498782363,1,1,.339526309,.528909511,1,1,.409505078,.558608486,1,1,.468487184,.588057293,1,1,.520796675,.617435078,1,1,.568724526,.646924167,1,1,.613686735,.676713218,1,1,.656658579,.707001303,1,1,.698372844,.738002964,1,1,.739424025,.769954435,1,1,.780330104,.803121429,1,1,.821573924,.837809045,1,1,.863634967,.874374691,1,1,.907017747,.913245283,1,1,.936129275,.938743558,.983038586,1,.943467973,.943498599,.943398095,1,.990146732,.928791426,.917447482,1,1,.88332677,.861943246,1,1,.833985467,.803839606,1,1,.788626485,.750707739,1,1,.746206642,.701389973,1,1,.70590052,.654994046,1,1,.667019783,.610806959,1,1,.6289553,.568237474,1,1,.591130233,.526775617,1,1,.552955184,.485962266,1,1,.513776083,.445364274,1,1,.472800903,.404551679,1,1,.428977855,.363073592,1,1,.380759558,.320428137,1,.961891484,.313155629,.265499262,1,.916482116,.236630659,.209939162,1].map(function(a){return 255*a}),this.setup=function(b){0===this.textureUnit()?b.m_context.activeTexture(c.GL.TEXTURE0):1===this.textureUnit()&&b.m_context.activeTexture(c.GL.TEXTURE1),b.m_context.deleteTexture(this.m_textureHandle),this.m_textureHandle=b.m_context.createTexture(),b.m_context.bindTexture(c.GL.TEXTURE_2D,this.m_textureHandle),b.m_context.texParameteri(c.GL.TEXTURE_2D,c.GL.TEXTURE_MIN_FILTER,c.GL.LINEAR),b.m_context.texParameteri(c.GL.TEXTURE_2D,c.GL.TEXTURE_MAG_FILTER,c.GL.LINEAR),b.m_context.texParameteri(c.GL.TEXTURE_2D,c.GL.TEXTURE_WRAP_S,c.GL.CLAMP_TO_EDGE),b.m_context.texParameteri(c.GL.TEXTURE_2D,c.GL.TEXTURE_WRAP_T,c.GL.CLAMP_TO_EDGE),b.m_context.pixelStorei(c.GL.UNPACK_ALIGNMENT,1),this.m_width=this.m_colorTable.length/4,this.m_height=1,this.m_depth=0,b.m_context.texImage2D(c.GL.TEXTURE_2D,0,c.GL.RGBA,this.m_width,this.m_height,this.m_depth,c.GL.RGBA,c.GL.UNSIGNED_BYTE,new Uint8Array(this.m_colorTable)),b.m_context.bindTexture(c.GL.TEXTURE_2D,null),a.modified()},this.colorTable=function(){return this.m_colorTable},this.setColorTable=function(a){return this.m_colorTable===a?!1:(this.m_colorTable=a,this.modified(),!0)},this.range=function(){return b},this.setRange=function(a){return b===a?!1:(b=a,this.modified(),!0)},this.updateRange=function(a){a instanceof Array||console.log("[error] Invalid data type for range. Requires array [min,max]"),a[0]b[1]&&(b[1]=a[1],this.modified())},this},a(c.lookupTable,c.texture),c.uniform=function(a,b){"use strict";if(!(this instanceof c.uniform))return new c.uniform;this.getTypeNumberOfComponents=function(a){switch(a){case c.GL.FLOAT:case c.GL.INT:case c.GL.BOOL:return 1;case c.GL.FLOAT_VEC2:case c.GL.INT_VEC2:case c.GL.BOOL_VEC2:return 2;case c.GL.FLOAT_VEC3:case c.GL.INT_VEC3:case c.GL.BOOL_VEC3:return 3;case c.GL.FLOAT_VEC4:case c.GL.INT_VEC4:case c.GL.BOOL_VEC4:return 4;case c.GL.FLOAT_MAT3:return 9;case c.GL.FLOAT_MAT4:return 16;default:return 0}};var d=a,e=b,f=[];return f.length=this.getTypeNumberOfComponents(d),this.name=function(){return e},this.type=function(){return d},this.get=function(){return f},this.set=function(a){var b=0;if(16===f.length)for(b=0;16>b;b+=1)f[b]=a[b];else if(9===f.length)for(b=0;9>b;b+=1)f[b]=a[b];else if(4===f.length)for(b=0;4>b;b+=1)f[b]=a[b];else if(3===f.length)for(b=0;3>b;b+=1)f[b]=a[b];else if(2===f.length)for(b=0;2>b;b+=1)f[b]=a[b];else f[0]=a},this.callGL=function(a,b){if(!(this.m_numberElements<1))switch(d){case c.GL.BOOL:case c.GL.INT:a.m_context.uniform1iv(b,f);break;case c.GL.FLOAT:a.m_context.uniform1fv(b,f);break;case c.GL.FLOAT_VEC2:a.m_context.uniform2fv(b,f);break;case c.GL.FLOAT_VEC3:a.m_context.uniform3fv(b,f);break;case c.GL.FLOAT_VEC4:a.m_context.uniform4fv(b,f);break;case c.GL.FLOAT_MAT3:a.m_context.uniformMatrix3fv(b,c.GL.FALSE,f);break;case c.GL.FLOAT_MAT4:a.m_context.uniformMatrix4fv(b,c.GL.FALSE,f)}},this.update=function(a,b){a=a,b=b},this},c.modelViewUniform=function(a){"use strict";return this instanceof c.modelViewUniform?(0===a.length&&(a="modelViewMatrix"),c.uniform.call(this,c.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.update=function(a,b){b=b,this.set(a.m_modelViewMatrix)},this):new c.modelViewUniform(a)},a(c.modelViewUniform,c.uniform),c.modelViewOriginUniform=function(a,b){"use strict";if(!(this instanceof c.modelViewOriginUniform))return new c.modelViewOriginUniform(a,b);0===a.length&&(a="modelViewMatrix"),b=b||[0,0,0];var d=[b[0],b[1],b[2]||0];return c.uniform.call(this,c.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.setOrigin=function(a){a=a||[0,0,0],d=[a[0],a[1],a[2]||0]},this.update=function(a,b){b=b;var c=mat4.create();if(mat4.translate(c,a.m_modelViewMatrix,d),a.m_modelViewAlignment){var e=a.m_modelViewAlignment;c[12]=Math.round(c[12]/e.roundx)*e.roundx+e.dx,c[13]=Math.round(c[13]/e.roundy)*e.roundy+e.dy}this.set(c)},this},a(c.modelViewOriginUniform,c.uniform),c.projectionUniform=function(a){"use strict";return this instanceof c.projectionUniform?(0===a.length&&(a="projectionMatrix"),c.uniform.call(this,c.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.update=function(a,b){b=b,this.set(a.m_projectionMatrix)},this):new c.projectionUniform(a)},a(c.projectionUniform,c.uniform),c.floatUniform=function(a,b){"use strict";return this instanceof c.floatUniform?(0===a.length&&(a="floatUniform"),b=void 0===b?1:b,c.uniform.call(this,c.GL.FLOAT,a),void this.set(b)):new c.floatUniform(a,b)},a(c.floatUniform,c.uniform),c.normalMatrixUniform=function(a){"use strict";return this instanceof c.normalMatrixUniform?(0===a.length&&(a="normalMatrix"),c.uniform.call(this,c.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.update=function(a,b){b=b,this.set(a.m_normalMatrix)},this):new c.normalMatrixUniform(a)},a(c.normalMatrixUniform,c.uniform),c.vertexAttributeKeys={Position:0,Normal:1,TextureCoordinate:2,Color:3,Scalar:4,CountAttributeIndex:5},c.vertexAttributeKeysIndexed={Zero:0,One:1,Two:2,Three:3,Four:4,Five:5,Six:6,Seven:7,Eight:8,Nine:9},c.vertexAttribute=function(a){"use strict";if(!(this instanceof c.vertexAttribute))return new c.vertexAttribute(a);var b=a;this.name=function(){return b},this.bindVertexData=function(a,c){var d=a.m_mapper.geometryData(),e=d.sourceData(c),f=a.m_material.shaderProgram();a.m_context.vertexAttribPointer(f.attributeLocation(b),e.attributeNumberOfComponents(c),e.attributeDataType(c),e.normalized(c),e.attributeStride(c),e.attributeOffset(c)),a.m_context.enableVertexAttribArray(f.attributeLocation(b))},this.undoBindVertexData=function(a,c){c=c;var d=a.m_material.shaderProgram();a.m_context.disableVertexAttribArray(d.attributeLocation(b))}},c.source=function(){"use strict";return this instanceof c.source?(c.object.call(this),this.create=function(){},this):new c.source},a(c.source,c.object),c.planeSource=function(){"use strict";if(!(this instanceof c.planeSource))return new c.planeSource;c.source.call(this);var a=[0,0,0],b=[1,0,0],d=[0,1,0],e=[0,0,1],f=1,g=1,h=null;this.setOrigin=function(b,c,d){a[0]=b,a[1]=c,a[2]=d},this.setPoint1=function(a,c,d){b[0]=a,b[1]=c,b[2]=d},this.setPoint2=function(a,b,c){d[0]=a,d[1]=b,d[2]=c},this.create=function(){h=new c.geometryData;var i,j,k,l,m,n,o,p=[],q=[],r=[],s=[],t=[],u=0,v=0,w=0,x=0,y=[],z=[],A=[],B=[],C=[],D=null,E=null,F=null;for(p.length=3,q.length=2,r.length=3,s.length=3,t.length=3,i=0;3>i;i+=1)r[i]=b[i]-a[i],s[i]=d[i]-a[i];for(m=(f+1)*(g+1),n=f*g*2,y.length=3*m,z.length=3*m,B.length=2*m,C.length=m,k=0,i=0;g+1>i;i+=1)for(q[1]=i/g,j=0;f+1>j;j+=1){for(q[0]=j/f,l=0;3>l;l+=1)p[l]=a[l]+q[0]*r[l]+q[1]*s[l];y[u++]=p[0],y[u++]=p[1],y[u++]=p[2],A[w++]=1,A[w++]=1,A[w++]=1,z[v++]=e[0],z[v++]=e[1],z[v++]=e[2],B[x++]=q[0],B[x++]=q[1]}for(i=0;g>i;i+=1)for(j=0;f>j;j+=1)t[0]=j+i*(f+1),t[1]=t[0]+1,t[2]=t[0]+f+2,t[3]=t[0]+f+1;for(i=0;m>i;i+=1)C[i]=i;return D=new c.triangleStrip,D.setIndices(C),E=c.sourceDataP3fv(),E.pushBack(y),F=c.sourceDataC3fv(),F.pushBack(A),o=c.sourceDataT2fv(),o.pushBack(B),h.addSource(E),h.addSource(F),h.addSource(o),h.addPrimitive(D),h}},a(c.planeSource,c.source),c.pointSource=function(){"use strict";if(!(this instanceof c.pointSource))return new c.pointSource;c.source.call(this);var a=this,b=[],d=[],e=[],f=[],g=null;this.getPositions=function(){return b},this.setPositions=function(c){c instanceof Array?b=c:console.log("[ERROR] Invalid data type for positions. Array is required."),a.modified()},this.getColors=function(){return d},this.setColors=function(b){b instanceof Array?d=b:console.log("[ERROR] Invalid data type for colors. Array is required."),a.modified()},this.getSize=function(){return f},this.setSize=function(a){f=a,this.modified()},this.setTextureCoordinates=function(b){b instanceof Array?e=b:console.log("[ERROR] Invalid data type for texture coordinates. Array is required."),a.modified()},this.create=function(){if(g=new c.geometryData,b.length%3!==0)return void console.log("[ERROR] Invalid length of the points array");var a,h,i,j,k,l=b.length/3,m=0,n=[];for(n.length=l,m=0;l>m;m+=1)n[m]=m;if(k=c.sourceDataDf(),l!==f.length)for(m=0;l>m;m+=1)k.pushBack(f);else k.setData(f);return g.addSource(k),a=new c.points,a.setIndices(n),h=c.sourceDataP3fv(),h.pushBack(b),g.addSource(h),d.length>0&&d.length===b.length?(i=c.sourceDataC3fv(),i.pushBack(d),g.addSource(i)):d.length>0&&d.length!==b.length&&console.log("[ERROR] Number of colors are different than number of points"),e.length>0&&e.length===b.length?(j=c.sourceDataT2fv(),j.pushBack(e),g.addSource(j)):e.length>0&&e.length/2!==b.length/3&&console.log("[ERROR] Number of texture coordinates are different than number of points"),g.addPrimitive(a),g}},a(c.pointSource,c.source),c.lineSource=function(a,b){"use strict";if(!(this instanceof c.lineSource))return new c.lineSource;c.source.call(this);var d=a,e=b;this.setPositions=function(a){return a instanceof Array?(d=a,this.modified(),!0):(console.log("[ERROR] Invalid data type for positions. Array is required."),!1)},this.setColors=function(a){return a instanceof Array?(e=a,this.modified(),!0):(console.log("[ERROR] Invalid data type for colors. Array is required."),!1)},this.create=function(){if(!d)return void console.log("[error] Invalid positions");if(d.length%3!==0)return void console.log("[error] Line source requires 3d points");if(d.length%3!==0)return void console.log("[ERROR] Invalid length of the points array");var a,b,f,g,h=new c.geometryData,i=d.length/3,j=[];for(j.length=i,a=0;i>a;a+=1)j[a]=a;return b=new c.lines,b.setIndices(j),f=c.sourceDataP3fv(),f.pushBack(d),h.addSource(f),e&&e.length>0&&e.length===d.length?(g=c.sourceDataC3fv(),g.pushBack(e),h.addSource(g)):e&&e.length>0&&e.length!==d.length&&console.log("[error] Number of colors are different than number of points"),h.addPrimitive(b),h}},a(c.lineSource,c.source),c.utils=function(){"use strict";return this instanceof c.utils?(c.object.call(this),this):new c.utils},a(c.utils,c.object),c.utils.computePowerOfTwo=function(a,b){"use strict";for(b=b||1;a>b;)b*=2;return b},c.utils.createTextureVertexShader=function(a){"use strict";var b=["attribute vec3 vertexPosition;","attribute vec3 textureCoord;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","varying highp vec3 iTextureCoord;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);"," iTextureCoord = textureCoord;","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,b)},c.utils.createTextureFragmentShader=function(a){"use strict";var b=["varying highp vec3 iTextureCoord;","uniform sampler2D sampler2d;","uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4(texture2D(sampler2d, vec2(iTextureCoord.s, iTextureCoord.t)).xyz, opacity);","}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,b)},c.utils.createRgbaTextureFragmentShader=function(a){"use strict";var b=["varying highp vec3 iTextureCoord;","uniform sampler2D sampler2d;","uniform mediump float opacity;","void main(void) {"," mediump vec4 color = vec4(texture2D(sampler2d, vec2(iTextureCoord.s, iTextureCoord.t)).xyzw);"," color.w *= opacity;"," gl_FragColor = color;","}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,b)},c.utils.createVertexShader=function(a){"use strict";var b=["attribute vec3 vertexPosition;","attribute vec3 vertexColor;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","varying mediump vec3 iVertexColor;","varying highp vec3 iTextureCoord;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);"," iVertexColor = vertexColor;","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,b)},c.utils.createPointVertexShader=function(a){"use strict";var b=["attribute vec3 vertexPosition;","attribute vec3 vertexColor;","attribute float vertexSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","varying mediump vec3 iVertexColor;","varying highp vec3 iTextureCoord;","void main(void)","{","gl_PointSize = vertexSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);"," iVertexColor = vertexColor;","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,b)},c.utils.createVertexShaderSolidColor=function(a){"use strict";var b=["attribute vec3 vertexPosition;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,b)},c.utils.createVertexShaderColorMap=function(a,b,d){"use strict";b=b,d=d;var e=["attribute vec3 vertexPosition;","attribute float vertexScalar;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float lutMin;","uniform float lutMax;","varying mediump float iVertexScalar;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);","iVertexScalar = (vertexScalar-lutMin)/(lutMax-lutMin);","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,e)},c.utils.createFragmentShader=function(a){"use strict";var b=["varying mediump vec3 iVertexColor;","uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4(iVertexColor, opacity);","}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,b)},c.utils.createPhongVertexShader=function(a){"use strict";var b=["attribute highp vec3 vertexPosition;","attribute mediump vec3 vertexNormal;","attribute mediump vec3 vertexColor;","uniform highp mat4 projectionMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 normalMatrix;","varying highp vec4 varPosition;","varying mediump vec3 varNormal;","varying mediump vec3 varVertexColor;","void main(void)","{","varPosition = modelViewMatrix * vec4(vertexPosition, 1.0);","gl_Position = projectionMatrix * varPosition;","varNormal = vec3(normalMatrix * vec4(vertexNormal, 0.0));","varVertexColor = vertexColor;","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,b)},c.utils.createPhongFragmentShader=function(a){"use strict";var b=["uniform mediump float opacity;","precision mediump float;","varying vec3 varNormal;","varying vec4 varPosition;","varying mediump vec3 varVertexColor;","const vec3 lightPos = vec3(0.0, 0.0,10000.0);","const vec3 ambientColor = vec3(0.01, 0.01, 0.01);","const vec3 specColor = vec3(0.0, 0.0, 0.0);","void main() {","vec3 normal = normalize(varNormal);","vec3 lightDir = normalize(lightPos);","vec3 reflectDir = -reflect(lightDir, normal);","vec3 viewDir = normalize(-varPosition.xyz);","float lambertian = max(dot(lightDir, normal), 0.0);","vec3 color = vec3(0.0);","if(lambertian > 0.0) {"," color = lambertian * varVertexColor;","}","gl_FragColor = vec4(color * opacity, 1.0 - opacity);","}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,b)},c.utils.createFragmentShaderSolidColor=function(a,b){"use strict";var d=["uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4("+b[0]+","+b[1]+","+b[2]+", opacity);","}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,d)},c.utils.createFragmentShaderColorMap=function(a){"use strict";var b=["varying mediump float iVertexScalar;","uniform sampler2D sampler2d;","uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4(texture2D(sampler2d, vec2(iVertexScalar, 0.0)).xyz, opacity);","}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,b)},c.utils.createPointSpritesVertexShader=function(a){"use strict";var b=["attribute vec3 vertexPosition;","attribute vec3 vertexColor;","uniform mediump vec2 pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float height;","varying mediump vec3 iVertexColor;","varying highp float iVertexScalar;","void main(void)","{","mediump float realPointSize = pointSize.y;","if (pointSize.x > pointSize.y) {"," realPointSize = pointSize.x;}","gl_PointSize = realPointSize ;","iVertexScalar = vertexPosition.z;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition.xy, height, 1.0);"," iVertexColor = vertexColor;","}"].join("\n");return c.getCachedShader(c.GL.VERTEX_SHADER,a,b)},c.utils.createPointSpritesFragmentShader=function(a){"use strict";var b=["varying mediump vec3 iVertexColor;","varying highp float iVertexScalar;","uniform sampler2D opacityLookup;","uniform highp float lutMin;","uniform highp float lutMax;","uniform sampler2D scalarsToColors;","uniform int useScalarsToColors;","uniform int useVertexColors;","uniform mediump vec2 pointSize;","uniform mediump float vertexColorWeight;","void main(void) {","mediump vec2 realTexCoord;","if (pointSize.x > pointSize.y) {"," realTexCoord = vec2(1.0, pointSize.y/pointSize.x) * gl_PointCoord;","} else {"," realTexCoord = vec2(pointSize.x/pointSize.y, 1.0) * gl_PointCoord;","}","highp float texOpacity = texture2D(opacityLookup, realTexCoord).w;","if (useScalarsToColors == 1) {"," gl_FragColor = vec4(texture2D(scalarsToColors, vec2((iVertexScalar - lutMin)/(lutMax - lutMin), 0.0)).xyz, texOpacity);","} else if (useVertexColors == 1) {"," gl_FragColor = vec4(iVertexColor, texOpacity);","} else {"," gl_FragColor = vec4(texture2D(opacityLookup, realTexCoord).xyz, texOpacity);","}}"].join("\n");return c.getCachedShader(c.GL.FRAGMENT_SHADER,a,b)},c.utils.createTextureMaterial=function(a,b){"use strict";var d,e=new c.material,f=new c.blend,g=new c.shaderProgram,h=c.utils.createTextureVertexShader(c.GL),i=null,j=new c.vertexAttribute("vertexPosition"),k=new c.vertexAttribute("textureCoord"),l=new c.floatUniform("pointSize",5),m=new c.projectionUniform("projectionMatrix"),n=new c.uniform(c.GL.INT,"sampler2d"),o=null;return d=void 0!==b?new c.modelViewOriginUniform("modelViewMatrix",b):new c.modelViewUniform("modelViewMatrix"),n.set(0),g.addVertexAttribute(j,c.vertexAttributeKeys.Position),g.addVertexAttribute(k,c.vertexAttributeKeys.TextureCoordinate),g.addUniform(l),g.addUniform(d),g.addUniform(m),i=a?c.utils.createRgbaTextureFragmentShader(c.GL):c.utils.createTextureFragmentShader(c.GL),o=new c.floatUniform("opacity",1),g.addUniform(o),g.addShader(i),g.addShader(h),e.addAttribute(g),e.addAttribute(f),e},c.utils.createGeometryMaterial=function(){"use strict";var a=new c.material,b=new c.shaderProgram,d=5,e=1,f=c.utils.createVertexShader(c.GL),g=c.utils.createFragmentShader(c.GL),h=new c.vertexAttribute("vertexPosition"),i=new c.vertexAttribute("vertexColor"),j=new c.floatUniform("pointSize",d),k=new c.floatUniform("opacity",e),l=new c.modelViewUniform("modelViewMatrix"),m=new c.projectionUniform("projectionMatrix");return b.addVertexAttribute(h,c.vertexAttributeKeys.Position),b.addVertexAttribute(i,c.vertexAttributeKeys.Color),b.addUniform(j),b.addUniform(k),b.addUniform(l),b.addUniform(m),b.addShader(g),b.addShader(f),a.addAttribute(b),a},c.utils.createPointGeometryMaterial=function(a){"use strict";a=void 0===a?1:a;var b=new c.material,d=new c.blend,e=new c.shaderProgram,f=c.utils.createPointVertexShader(c.GL),g=c.utils.createFragmentShader(c.GL),h=new c.vertexAttribute("vertexPosition"),i=new c.vertexAttribute("vertexColor"),j=new c.vertexAttribute("vertexSize"),k=new c.floatUniform("opacity",a),l=new c.modelViewUniform("modelViewMatrix"),m=new c.projectionUniform("projectionMatrix");return e.addVertexAttribute(h,c.vertexAttributeKeys.Position),e.addVertexAttribute(i,c.vertexAttributeKeys.Color),e.addVertexAttribute(j,c.vertexAttributeKeys.Scalar),e.addUniform(k),e.addUniform(l),e.addUniform(m),e.addShader(g),e.addShader(f),b.addAttribute(e),b.addAttribute(d),b},c.utils.createPhongMaterial=function(){"use strict";var a=new c.material,b=new c.shaderProgram,d=c.utils.createPhongVertexShader(c.GL),e=c.utils.createPhongFragmentShader(c.GL),f=new c.vertexAttribute("vertexPosition"),g=new c.vertexAttribute("vertexNormal"),h=new c.vertexAttribute("vertexColor"),i=new c.floatUniform("opacity",1),j=new c.modelViewUniform("modelViewMatrix"),k=new c.normalMatrixUniform("normalMatrix"),l=new c.projectionUniform("projectionMatrix");return b.addVertexAttribute(f,c.vertexAttributeKeys.Position),b.addVertexAttribute(g,c.vertexAttributeKeys.Normal),b.addVertexAttribute(h,c.vertexAttributeKeys.Color),b.addUniform(i),b.addUniform(j),b.addUniform(l),b.addUniform(k),b.addShader(e),b.addShader(d),a.addAttribute(b),a},c.utils.createColorMaterial=function(){"use strict";var a=new c.material,b=new c.blend,d=new c.shaderProgram,e=c.utils.createVertexShader(c.GL),f=c.utils.createFragmentShader(c.GL),g=new c.vertexAttribute("vertexPosition"),h=new c.vertexAttribute("textureCoord"),i=new c.vertexAttribute("vertexColor"),j=new c.floatUniform("pointSize",5),k=new c.floatUniform("opacity",1),l=new c.modelViewUniform("modelViewMatrix"),m=new c.projectionUniform("projectionMatrix");return d.addVertexAttribute(g,c.vertexAttributeKeys.Position),d.addVertexAttribute(i,c.vertexAttributeKeys.Color),d.addVertexAttribute(h,c.vertexAttributeKeys.TextureCoordinate),d.addUniform(j),d.addUniform(k),d.addUniform(l),d.addUniform(m),d.addShader(f),d.addShader(e),a.addAttribute(d),a.addAttribute(b),a},c.utils.createColorMappedMaterial=function(a){"use strict";a||(a=new c.lookupTable);var b=a.range(),d=new c.material,e=new c.blend,f=new c.shaderProgram,g=c.utils.createVertexShaderColorMap(c.GL,b[0],b[1]),h=c.utils.createFragmentShaderColorMap(c.GL),i=new c.vertexAttribute("vertexPosition"),j=new c.vertexAttribute("vertexScalar"),k=new c.floatUniform("pointSize",5),l=new c.floatUniform("opacity",1),m=new c.floatUniform("lutMin",b[0]),n=new c.floatUniform("lutMax",b[1]),o=new c.modelViewUniform("modelViewMatrix"),p=new c.projectionUniform("projectionMatrix"),q=new c.uniform(c.GL.FLOAT,"sampler2d"),r=a;return q.set(0),f.addVertexAttribute(i,c.vertexAttributeKeys.Position),f.addVertexAttribute(j,c.vertexAttributeKeys.Scalar),f.addUniform(k),f.addUniform(l),f.addUniform(m),f.addUniform(n),f.addUniform(o),f.addUniform(p),f.addShader(h),f.addShader(g),d.addAttribute(f),d.addAttribute(e),d.addAttribute(r),d},c.utils.updateColorMappedMaterial=function(a,b){"use strict";if(!a)return void console.log("[warning] Invalid material. Nothing to update.");if(!b)return void console.log("[warning] Invalid lookup table. Nothing to update.");var c=a.shaderProgram().uniform("lutMin"),d=a.shaderProgram().uniform("lutMax");c.set(b.range()[0]),d.set(b.range()[1]),a.setAttribute(b)},c.utils.createSolidColorMaterial=function(a){"use strict";a||(a=[1,1,1]);var b=new c.material,d=new c.blend,e=new c.shaderProgram,f=c.utils.createVertexShaderSolidColor(c.GL),g=c.utils.createFragmentShaderSolidColor(c.GL,a),h=new c.vertexAttribute("vertexPosition"),i=new c.floatUniform("pointSize",5),j=new c.floatUniform("opacity",1),k=new c.modelViewUniform("modelViewMatrix"),l=new c.projectionUniform("projectionMatrix");return e.addVertexAttribute(h,c.vertexAttributeKeys.Position),e.addUniform(i),e.addUniform(j),e.addUniform(k),e.addUniform(l),e.addShader(g),e.addShader(f),b.addAttribute(e),b.addAttribute(d),b},c.utils.createPointSpritesMaterial=function(a,b){"use strict";var d=void 0===b?[0,1]:b.range(),e=new c.material,f=new c.blend,g=new c.shaderProgram,h=c.utils.createPointSpritesVertexShader(c.GL),i=c.utils.createPointSpritesFragmentShader(c.GL),j=new c.vertexAttribute("vertexPosition"),k=new c.vertexAttribute("vertexColor"),l=new c.floatUniform("height",0),m=new c.floatUniform("vertexColorWeight",0),n=new c.floatUniform("lutMin",d[0]),o=new c.floatUniform("lutMax",d[1]),p=new c.modelViewUniform("modelViewMatrix"),q=new c.projectionUniform("projectionMatrix"),r=new c.uniform(c.GL.INT,"opacityLookup"),s=new c.uniform(c.GL.INT,"scalarsToColors"),t=new c.uniform(c.GL.INT,"useScalarsToColors"),u=new c.uniform(c.GL.INT,"useVertexColors"),v=new c.uniform(c.GL.FLOAT_VEC2,"pointSize"),w=new c.texture;return r.set(0),s.set(1),t.set(0),u.set(0),v.set([1,1]),g.addVertexAttribute(j,c.vertexAttributeKeys.Position),g.addVertexAttribute(k,c.vertexAttributeKeys.Color),g.addUniform(l),g.addUniform(m),g.addUniform(p),g.addUniform(q),g.addUniform(r),g.addUniform(u),g.addUniform(t),g.addUniform(v),g.addShader(i),g.addShader(h),e.addAttribute(g),e.addAttribute(f),b&&(g.addUniform(s),t.set(1),g.addUniform(n),g.addUniform(o),b.setTextureUnit(1),e.addAttribute(b)),w.setImage(a),w.setTextureUnit(0),e.addAttribute(w),e},c.utils.createPlane=function(a,b,d,e,f,g,h,i,j){"use strict";var k=new c.mapper,l=new c.planeSource,m=c.utils.createGeometryMaterial(),n=new c.actor;return l.setOrigin(a,b,d),l.setPoint1(e,f,g),l.setPoint2(h,i,j),k.setGeometryData(l.create()),n.setMapper(k),n.setMaterial(m),n},c.utils.createTexturePlane=function(a,b,d,e,f,g,h,i,j,k){"use strict";var l=new c.mapper,m=new c.planeSource,n=c.utils.createTextureMaterial(k,[a,b,d]),o=new c.actor;return m.setPoint1(e-a,f-b,g-d),m.setPoint2(h-a,i-b,j-d),l.setGeometryData(m.create()),o.setMapper(l),o.setMaterial(n),o},c.utils.createPoints=function(a,b,d,e,f){"use strict";if(!a)return console.log("[ERROR] Cannot create points without positions"),null;f=void 0===f?1:f;var g=new c.mapper,h=new c.pointSource,i=c.utils.createPointGeometryMaterial(f),j=new c.actor;return h.setPositions(a),d&&h.setColors(d),e&&h.setTextureCoordinates(e),b?h.setSize(b):h.setSize(1),g.setGeometryData(h.create()),j.setMapper(g),j.setMaterial(i),j},c.utils.createPointSprites=function(a,b,d,e){"use strict";if(!a)return console.log("[ERROR] Point sprites requires an image"),null;if(!b)return console.log("[ERROR] Cannot create points without positions"),null;var f=new c.mapper,g=new c.pointSource,h=c.utils.createPointSpritesMaterial(a),i=new c.actor;return g.setPositions(b),d&&g.setColors(d),e&&g.setTextureCoordinates(e),f.setGeometryData(g.create()),i.setMapper(f),i.setMaterial(h),i},c.utils.createLines=function(a,b){"use strict";if(!a)return console.log("[ERROR] Cannot create points without positions"),null;var d=new c.mapper,e=new c.lineSource,f=c.utils.createGeometryMaterial(),g=new c.actor;return e.setPositions(a), -b&&e.setColors(b),d.setGeometryData(e.create()),g.setMapper(d),g.setMaterial(f),g},c.utils.createColorLegend=function(a,b,d,e,f,g,h){"use strict";function i(a,b,d){if(!b)return void console.log("[error] Create labels requires positions (x,y,z) array");if(b.length%3!==0)return void console.log("[error] Create labels require positions array contain 3d points");if(!d)return void console.log("[error] Create labels requires Valid range");var e,f=null,g=c.utils.computePowerOfTwo(48),h=0,i=[],j=[],k=[],l=[],m=b[6]-b[0],n=4;for(j.length=3,k.length=3,l.length=3,e=0;2>e;e+=1)h=e*(b.length-3),j[0]=b[h]-m,j[1]=b[h+1]-2*m,j[2]=b[h+2],k[0]=b[h]+m,k[1]=j[1],k[2]=j[2],l[0]=j[0],l[1]=b[1],l[2]=j[2],f=c.utils.createTexturePlane(j[0],j[1],j[2],k[0],k[1],k[2],l[0],l[1],l[2],!0),f.setReferenceFrame(c.boundingObject.ReferenceFrame.Absolute),f.material().setBinNumber(c.material.RenderBin.Overlay),f.material().addAttribute(c.utils.create2DTexture(d[e].toFixed(2).toString(),12,null)),i.push(f);return j[0]=.5*(b[0]+b[b.length-3]-g),j[1]=b[1]+n,j[2]=b[2],k[0]=j[0]+g,k[1]=j[1],k[2]=j[2],l[0]=j[0],l[1]=j[1]+g,l[2]=j[2],f=c.utils.createTexturePlane(j[0],j[1],j[2],k[0],k[1],k[2],l[0],l[1],l[2],!0),f.setReferenceFrame(c.boundingObject.ReferenceFrame.Absolute),f.material().setBinNumber(c.material.RenderBin.Overlay),f.material().addAttribute(c.utils.create2DTexture(a,24,null)),i.push(f),i}function j(a,b,c,d,e,f,g,h,j,k,l,m,n,o,p){p=p;var q=j-f,r=null,s=q/m,t=[],u=[];for(r=0;m>=r;r+=1)t.push(f+s*r),t.push(g),t.push(h),t.push(f+s*r),t.push(g+o),t.push(h);return u=u.concat(i(a,t,b.range()))}if(!b)return console.log("[error] Invalid lookup table"),[];var k=d[0]+e,l=d[1],m=0,n=d[0],o=d[1]+f,p=0,q=[],r=null,s=null,t=c.groupNode();return r=c.utils.createTexturePlane(d[0],d[1],d[2],k,l,m,n,o,p,!0),s=r.material(),s.addAttribute(b),r.setMaterial(s),t.addChild(r),r.material().setBinNumber(c.material.RenderBin.Overlay),r.setReferenceFrame(c.boundingObject.ReferenceFrame.Absolute),q.push(r),q=q.concat(j(a,b,d[0],d[1],d[1],n,l,m,k,l,m,g,h,5,3))},c.utils.create2DTexture=function(a,b,d,e,f,g,h){"use strict";var i=document.getElementById("textRendering"),j=null,k=c.texture();return e=e||"sans-serif",f=f||"center",g=g||"bottom","undefined"==typeof h&&(h=!0),i||(i=document.createElement("canvas")),j=i.getContext("2d"),i.setAttribute("id","textRendering"),i.style.display="none",i.height=c.utils.computePowerOfTwo(8*b),i.width=i.height,j.fillStyle="rgba(0, 0, 0, 0)",j.fillRect(0,0,j.canvas.width,j.canvas.height),j.fillStyle="rgba(200, 85, 10, 1.0)",j.textAlign=f,j.textBaseline=g,j.font=4*b+"px "+e,h&&(j.font="bold "+j.font),j.fillText(a,i.width/2,i.height/2,i.width),k.setImage(i),k.updateDimensions(),k},c.picker=function(){"use strict";if(!(this instanceof c.picker))return new c.picker;c.object.call(this);var a=[];return this.getActors=function(){return a},this.pick=function(b,c,d){if(void 0===b)return 0;if(void 0===c)return 0;if(void 0===d)return 0;a=[];var e,f,g,h,i,j,k,l,m,n,o,p=d.camera(),q=d.width(),r=d.height(),s=p.focalPoint(),t=vec4.fromValues(s[0],s[1],s[2],1),u=d.worldToDisplay(t,p.viewMatrix(),p.projectionMatrix(),q,r),v=vec4.fromValues(b,c,u[2],1),w=d.displayToWorld(v,p.viewMatrix(),p.projectionMatrix(),q,r),x=p.position(),y=[];for(g=0;3>g;g+=1)y[g]=w[g]-x[g];for(e=d.sceneRoot().children(),f=0,g=0;g=0?(i=(h[0]-x[0])/y[0],j=(h[1]-x[0])/y[0]):(i=(h[1]-x[0])/y[0],j=(h[0]-x[0])/y[0]),y[1]>=0?(k=(h[2]-x[1])/y[1],l=(h[3]-x[1])/y[1]):(k=(h[3]-x[1])/y[1],l=(h[2]-x[1])/y[1]),i>l||k>j)continue;if(k>i&&(i=k),j>l&&(j=l),y[2]>=0?(m=(h[4]-x[2])/y[2],n=(h[5]-x[2])/y[2]):(m=(h[5]-x[2])/y[2],n=(h[4]-x[2])/y[2]),i>n||m>j)continue;m>i&&(i=m),j>n&&(j=n),a[f]=o,f+=1}return f},this},a(c.picker,c.object),c.shapefileReader=function(){"use strict";if(!(this instanceof c.shapefileReader))return new c.shapefileReader;var a=this,b=0,d=1,e=5,f=3;return this.int8=function(a,b){return a.charCodeAt(b)},this.bint32=function(a,b){return((255&a.charCodeAt(b))<<24)+((255&a.charCodeAt(b+1))<<16)+((255&a.charCodeAt(b+2))<<8)+(255&a.charCodeAt(b+3))},this.lint32=function(a,b){return((255&a.charCodeAt(b+3))<<24)+((255&a.charCodeAt(b+2))<<16)+((255&a.charCodeAt(b+1))<<8)+(255&a.charCodeAt(b))},this.bint16=function(a,b){return((255&a.charCodeAt(b))<<8)+(255&a.charCodeAt(b+1))},this.lint16=function(a,b){return((255&a.charCodeAt(b+1))<<8)+(255&a.charCodeAt(b))},this.ldbl64=function(a,b){var c=255&a.charCodeAt(b),d=255&a.charCodeAt(b+1),e=255&a.charCodeAt(b+2),f=255&a.charCodeAt(b+3),g=255&a.charCodeAt(b+4),h=255&a.charCodeAt(b+5),i=255&a.charCodeAt(b+6),j=255&a.charCodeAt(b+7),k=1-2*(j>>7),l=((127&j)<<4)+((240&i)>>4)-1023,m=(15&i)*Math.pow(2,48)+h*Math.pow(2,40)+g*Math.pow(2,32)+f*Math.pow(2,24)+e*Math.pow(2,16)+d*Math.pow(2,8)+c;return k*(1+m*Math.pow(2,-52))*Math.pow(2,l)},this.lfloat32=function(a,b){var c=255&a.charCodeAt(b),d=255&a.charCodeAt(b+1),e=255&a.charCodeAt(b+2),f=255&a.charCodeAt(b+3),g=1-2*(f>>7),h=((127&f)<<1)+((254&e)>>7)-127,i=(127&e)*Math.pow(2,16)+d*Math.pow(2,8)+c;return g*(1+i*Math.pow(2,-23))*Math.pow(2,h)},this.str=function(a,b,c){for(var d=[],e=b;b+c>e;){var f=a[e];if(0===f.charCodeAt(0))break;d.push(f),e+=1}return d.join("")},this.readHeader=function(a){var b=this.bint32(a,0),c=this.bint32(a,24),d=this.lint32(a,28),e=this.lint32(a,32);return{code:b,length:c,version:d,shapetype:e}},this.loadShx=function(b){for(var c=[],d=function(d){return c.push(2*a.bint32(b,d)),d+8},e=100;ej;)k.push(c(j)),j+=i;for(var l=[],m=f;f+e*g>m;){var n=a.str(b,m,1);if("*"===n)m+=g;else{m+=1;for(var o={},p=0;p=d;g-=1){var h=a.ldbl64(c,b+16*g),i=a.ldbl64(c,b+16*g+8);f.push([h,i])}return f},m=function(g){var h,i,j,m,n,o,p,q,r,s=g+8,t=a.lint32(c,s);if(t===b)console.log("NULL Shape");else if(t===d){var u=a.ldbl64(c,s+4),v=a.ldbl64(c,s+12);k.push({type:"Point",attr:{},geom:[[u,v]]})}else if(t===e){for(h=a.lint32(c,s+36),i=a.lint32(c,s+40),j=g+52,m=g+52+4*h,r=[],n=0;h>n;n+=1)o=a.lint32(c,j+4*n),p=h>n+1?a.lint32(c,j+4*(n+1)):i,q=l(m,o,p),r.push(q);k.push({type:"Polygon",attr:{},geom:[r]})}else{if(t!==f)throw"Not Implemented: "+t;for(h=a.lint32(c,s+36),i=a.lint32(c,s+40),j=g+52,m=g+52+4*h,r=[],n=0;h>n;n+=1)o=a.lint32(c,j+4*n),p=h>n+1?a.lint32(c,j+4*(n+1)):i,q=l(m,o,p),r.push(q);k.push({type:"Polyline",attr:{},geom:[r]})}},n=this.loadDBF(g);for(j=0;j=i.length)return h;if(a=i.charAt(j),j+=1,b[a])return b[a];if("A"===a)return 0}return h},this.decode64=function(a){var b="",c=new Array(4),d=!1;for(i=a,j=0;!d&&(c[0]=this.readReverseBase64())!==h&&(c[1]=this.readReverseBase64())!==h;)c[2]=this.readReverseBase64(),c[3]=this.readReverseBase64(),b+=this.ntos(c[0]<<2&255|c[1]>>4),c[2]!==h?(b+=this.ntos(c[1]<<4&255|c[2]>>2),c[3]!==h?b+=this.ntos(c[2]<<6&255|c[3]):d=!0):d=!0;return b},this.readNumber=function(a){var b=a[k++]+(a[k++]<<8)+(a[k++]<<16)+(a[k++]<<24);return b},this.readF3Array=function(a,b){var c,d=4*a*3,e=new Int8Array(d),f=null;for(c=0;d>c;c+=1)e[c]=b[k],k+=1;return f=new Float32Array(e.buffer)},this.readColorArray=function(a,b,c){var d,e=0,f=new Array(3*a);for(d=0;a>d;d+=1)f[e++]=b[k++]/255,f[e++]=b[k++]/255,f[e++]=b[k++]/255,k++;c.insert(f)},this.parseObject=function(a){var b,d,e,f,g,h,i,j,n,o,p,q=new c.geometryData,r=c.mapper(),s=[],t=null,u=null,v=null,w=null;for(u=atob(a.data),m=0;ml;l+=1)q[r++]=f[3*l],q[r++]=f[3*l+1],q[r++]=f[3*l+2];for(m.insert(q),a.addSource(m),n=new c.sourceDataC3fv,this.readColorArray(e,b,n),a.addSource(n),o=new c.lines,a.addPrimitive(o),d=this.readNumber(b),g=new Int8Array(2*d),l=0;2*d>l;l+=1)g[l]=b[k],k+=1;for(h=new Uint16Array(g.buffer),o.setIndices(h),o.setPrimitiveType(c.GL.LINES),i=64,g=new Int8Array(i),l=0;i>l;l+=1)g[l]=b[k],k+=1;return j=new Float32Array(g.buffer),mat4.copy(p,j),p},this.parseMeshData=function(a,b){var d,e,f,g,h,i,j,l,m,n=null,o=null,p=null,q=mat4.create(),r=null,s=null,t=0;for(e=this.readNumber(b),s=new Array(6*e),n=new c.sourceDataP3N3f,f=this.readF3Array(e,b),p=this.readF3Array(e,b),l=0;e>l;l+=1)s[t++]=f[3*l],s[t++]=f[3*l+1],s[t++]=f[3*l+2],s[t++]=p[3*l],s[t++]=p[3*l+1],s[t++]=p[3*l+2];for(n.insert(s),a.addSource(n),o=new c.sourceDataC3fv,this.readColorArray(e,b,o),a.addSource(o),g=[],r=new c.triangles,d=this.readNumber(b),g=new Int8Array(2*d),l=0;2*d>l;l+=1)g[l]=b[k],k+=1;for(h=new Uint16Array(g.buffer),r.setIndices(h),a.addPrimitive(r),i=64,g=new Int8Array(i),l=0;i>l;l+=1)g[l]=b[k],k+=1;return j=new Float32Array(g.buffer),mat4.copy(q,j),m=null,q},this.parsePointData=function(a,b){var d,e,f,g,h,i,j=mat4.create(),l=null,n=null,o=null,p=null,q=0;for(d=this.readNumber(b),p=new Array(3*d),l=new c.sourceDataP3fv,e=this.readF3Array(d,b),f=new Uint16Array(d),m=0;d>m;m+=1)f[m]=m,p[q++]=e[3*m],p[q++]=e[3*m+1],p[q++]=e[3*m+2];for(l.insert(p),a.addSource(l),n=new c.sourceDataC3fv,this.readColorArray(d,b,n),a.addSource(n),o=new c.points,o.setIndices(f),a.addPrimitive(o),h=64,g=new Int8Array(h),m=0;h>m;m+=1)g[m]=b[k],k+=1;return i=new Float32Array(g.buffer),mat4.copy(j,i),j},this.parseColorMapData=function(a,b,c){var d,e,f,g,h,i={};for(i.numOfColors=c,e=8,d=new Int8Array(e),g=0;e>g;g+=1)d[g]=b[k],k+=1;for(i.position=new Float32Array(d.buffer),e=8,d=new Int8Array(e),g=0;e>g;g+=1)d[g]=b[k],k+=1;for(i.size=new Float32Array(d.buffer),i.colors=[],h=0;hg;g+=1)d[g]=b[k],k+=1;f=[new Float32Array(d.buffer)[0],b[k++],b[k++],b[k++]],i.colors[h]=f}for(i.orientation=b[k++],i.numOfLabels=b[k++],i.title="";k=0;b-=1)a=this.getRenderer(b),this.parseSceneMetadata(a,b);return l},this.createViewer=function(a){var b;return null===l&&(g=a,l=c.viewer(a),l.init(),l.renderWindow().removeRenderer(l.renderWindow().activeRenderer()),l.renderWindow().addRenderer(new c.depthPeelRenderer),d[0]=l.renderWindow().activeRenderer(),l.renderWindow().resize(a.width,a.height),b=c.pvwInteractorStyle(),l.setInteractorStyle(b)),l},this.deleteViewer=function(){d={},l=null},this.updateCanvas=function(a){return g=a,l.renderWindow().resize(a.width,a.height),l},this.numObjects=function(){return e},this.getRenderer=function(a){var b;return b=d[a],(null===b||"undefined"==typeof b)&&(b=new c.renderer,b.setResetScene(!1),b.setResetClippingRange(!1),l.renderWindow().addRenderer(b),0!==a&&b.camera().setClearMask(c.GL.DepthBufferBit),d[a]=b),b},this.setVtkScene=function(a){f=a},this},c.DataBuffers=function(a){"use strict";if(!(this instanceof c.DataBuffers))return new c.DataBuffers(a);var b,d={};b=a||0===a?a:256;var e=0,f=function(a,b,c,d){a||console.log("ack"),c||(c=0),d||(d=b.length);for(var e=0;d>e;e+=1)a[c+e]=b[e]},g=function(a){var c=b;for(a>2*c&&(c=a);a>c;)c*=2;b=c;for(var e in d)if(d.hasOwnProperty(e)){var g=new Float32Array(c*d[e].len),h=d[e].array;f(g,h),d[e].array=g,d[e].dirty=!0}};this.create=function(a,c){if(!c)throw"Length of buffer must be a positive integer";var e=new Float32Array(b*c);return d[a]={array:e,len:c,dirty:!1},d[a].array},this.alloc=function(a){e+a>=b&&g(e+a);var c=e;return e+=a,c},this.get=function(a){return d[a].array},this.write=function(a,b,c,e){f(d[a].array,b,c*d[a].len,e*d[a].len),d[a].dirty=!0},this.repeat=function(a,b,c,e){for(var g=0;e>g;g+=1)f(d[a].array,b,(c+g)*d[a].len,d[a].len);d[a].dirty=!0},this.count=function(){return e},this.data=function(a){return d[a].array}},c}); +!function(a,b){"function"==typeof define&&define.amd?define("vgl",[],function(){return a.vgl=b()}):"object"==typeof module&&module.exports?module.exports=b():a.vgl=b()}(this,function(){if("undefined"==typeof a)var a={};a.namespace=function(b){"use strict";var c,d=b.split("."),e=a;for("ogs"===d[0]&&(d=d.slice(1)),c=0;c=0)return a.splice(c,1),b.setParent(null),this.boundsDirtyTimestamp().modified(),!0}},this.removeChildren=function(){for(;a.length;)this.removeChild(a[0]);this.modified()},this.children=function(){return a},this.hasChild=function(b){var c=0,d=!1;for(c=0;cthis.computeBoundsTimestamp().getMTime()&&this.parent().boundsDirtyTimestamp().modified(),this.computeBounds(),b.mode()===b.TraverseAllChildren)for(c=0;cthis.boundsDirtyTimestamp().getMTime()))for(b=0;bb;b+=1)e=2*b,f=2*b+1,d[e]c[f]&&(c[f]=d[f]);this.setBounds(c[0],c[1],c[2],c[3],c[4],c[5])}},this},inherit(b.groupNode,b.node),b.actor=function(){"use strict";if(!(this instanceof b.actor))return new b.actor;b.node.call(this);var a=this,c=mat4.create(),d=b.boundingObject.ReferenceFrame.Relative,e=null;return this.matrix=function(){return c},this.setMatrix=function(b){b!==c&&(c=b,a.modified())},this.referenceFrame=function(){return d},this.setReferenceFrame=function(b){return b!==d?(d=b,a.modified(),!0):!1},this.mapper=function(){return e},this.setMapper=function(b){b!==e&&(e=b,a.boundsModified())},this.accept=function(a){a=a},this.ascend=function(a){a=a},this.computeLocalToWorldMatrix=function(a,b){a=a,b=b},this.computeWorldToLocalMatrix=function(a,b){a=a,b=b},this.computeBounds=function(){if(null===e||void 0===e)return void a.resetBounds();var b,d,f,g,h=a.computeBoundsTimestamp();(a.boundsDirtyTimestamp().getMTime()>h.getMTime()||e.boundsDirtyTimestamp().getMTime()>h.getMTime())&&(e.computeBounds(),b=e.bounds(),d=[b[0],b[2],b[4]],f=[b[1],b[3],b[5]],vec3.transformMat4(d,d,c),vec3.transformMat4(f,f,c),g=[d[0]>f[0]?f[0]:d[0],d[0]>f[0]?d[0]:f[0],d[1]>f[1]?f[1]:d[1],d[1]>f[1]?d[1]:f[1],d[2]>f[2]?f[2]:d[2],d[2]>f[2]?d[2]:f[2]],a.setBounds(g[0],g[1],g[2],g[3],g[4],g[5]),h.modified())},a},inherit(b.actor,b.node),b.freezeObject=function(a){"use strict";var b=Object.freeze?Object.freeze(a):void 0;return"undefined"==typeof b?a:b},b.defaultValue=function(a,b){"use strict";return"undefined"!=typeof a?a:b},b.defaultValue.EMPTY_OBJECT=b.freezeObject({}),b.graphicsObject=function(a){"use strict";if(a=a,!(this instanceof b.graphicsObject))return new b.graphicsObject;b.object.call(this);var c=this;return this._setup=function(a){return a=a,!1},this._cleanup=function(a){return a=a,!1},this.bind=function(a){return a=a,!1},this.undoBind=function(a){return a=a,!1},this.render=function(a){return a=a,!1},this.remove=function(a){c._cleanup(a)},c},inherit(b.graphicsObject,b.object),b.geojsonReader=function(){"use strict";return this instanceof b.geojsonReader?(this.readScalars=function(a,c,d,e){var f=null,g=null,h=null,i=null,j=null;"values"===this.m_scalarFormat&&4===a.length?(g=a[3],f=c.sourceData(b.vertexAttributeKeys.Scalar),f||(f=new b.sourceDataSf,this.m_scalarRange&&f.setScalarRange(this.m_scalarRange[0],this.m_scalarRange[1]),void 0!==d&&(f.data().length=d),c.addSource(f)),void 0===d?f.pushBack(g):f.insertAt(e,g)):"rgb"===this.m_scalarFormat&&6===a.length&&(f=c.sourceData(b.vertexAttributeKeys.Color),f||(f=new b.sourceDataC3fv,void 0!==d&&(f.length=3*d),c.addSource(f)),h=a[3],i=a[4],j=a[5],void 0===d?f.pushBack([h,i,j]):f.insertAt(e,[h,i,j]))},this.readPoint=function(a){var c=new b.geometryData,d=new b.points,e=new b.sourceDataP3fv,f=new Uint16Array(1),g=null,h=null,i=null,j=null;for(c.addSource(e),j=0;1>j;j+=1)f[j]=j,g=a[0],h=a[1],i=0,a.length>2&&(i=a[2]),e.pushBack([g,h,i]),this.readScalars(a,c);return d.setIndices(f),c.addPrimitive(d),c.setName("aPoint"),c},this.readMultiPoint=function(a){var c,d=new b.geometryData,e=new b.points,f=new b.sourceDataP3fv,g=new Uint16Array(a.length),h=0,i=a.length,j=null,k=null,l=null;for(f.data().length=3*i,c=0;c2&&(l=a[c][2]),f.insertAt(h,[j,k,l]),this.readScalars(a[c],d,i,h),h+=1;return e.setIndices(g),d.addPrimitive(e),d.addSource(f),d.setName("manyPoints"),d},this.readLineString=function(a){var c=new b.geometryData,d=new b.lineStrip,e=new b.sourceDataP3fv,f=[],g=null,h=null,i=null,j=null;for(d.setIndicesPerPrimitive(a.length),g=0;g2&&(j=a[g][2]),e.pushBack([h,i,j]),this.readScalars(a[g],c);return d.setIndices(f),c.addPrimitive(d),c.addSource(e),c.setName("aLineString"),c},this.readMultiLineString=function(a){var c=new b.geometryData,d=new b.sourceDataP3fv,e=0,f=2*a.length,g=null,h=null,i=null,j=null,k=null,l=null,m=null,n=null;for(d.data().length=3*f,h=0;hg;g+=1)l.push(e),i=a[h][g][0],j=a[h][g][1],k=0,a[h][g].length>2&&(k=a[h][g][2]),d.insertAt(e,[i,j,k]),this.readScalars(a[h][g],c,2*f,e),e+=1;m.setIndices(l),c.addPrimitive(m)}return c.setName("aMultiLineString"),c.addSource(d),c},this.readPolygon=function(a){var c=new b.geometryData,d=new b.sourceDataP3fv,e=null,f=null,g=null,h=a[0].length,i=1,j=null,k=null,l=null;for(j=0;h>j;j+=1)e=a[0][j][0],f=a[0][j][1],g=0,a[0][j].length>2&&(g=a[0][j][2]),d.pushBack([e,f,g]),this.readScalars(a[0][j],c),j>1&&(k=new Uint16Array([0,i,j]),l=new b.triangles,l.setIndices(k),c.addPrimitive(l),i=j);return c.setName("POLY"),c.addSource(d),c},this.readMultiPolygon=function(a){var c=new b.geometryData,d=new b.sourceDataP3fv,e=0,f=a.length,g=0,h=3*f,i=new b.triangles,j=[],k=null,l=null,m=null,n=null,o=null,p=null,q=null,r=null,s=null,t=!1,u=0;for(d.data().length=3*f,l=0;f>l;l+=1)for(p=a[l][0].length,q=e,r=e+1,s=[!1,!1,!1],k=0;p>k;k+=1)m=a[l][0][k][0],n=a[l][0][k][1],o=0,a[l][0][k].length>2&&(o=a[l][0][k][2]),t=!1,m>180&&(t=!0,m-=360),0===k?s[0]=t:s[1+(k-1)%2]=t,d.insertAt(g,[m,n,o]),this.readScalars(a[l][0][k],c,h,g),g+=1,k>1&&(s[0]===s[1]&&s[1]===s[2]&&(j[3*u+0]=q,j[3*u+1]=r,j[3*u+2]=e,u+=1),r=e),e+=1;return i.setIndices(j),c.addPrimitive(i),c.setName("aMultiPoly"),c.addSource(d),c},this.readGJObjectInt=function(a){if(!a.hasOwnProperty("type"))return null;a.properties&&a.properties.ScalarFormat&&"values"===a.properties.ScalarFormat&&(this.m_scalarFormat="values",a.properties.ScalarRange&&(this.m_scalarRange=a.properties.ScalarRange)),a.properties&&a.properties.ScalarFormat&&"rgb"===a.properties.ScalarFormat&&(this.m_scalarFormat="rgb");var b,c=a.type,d=null,e=null,f=null;switch(c){case"Point":b=this.readPoint(a.coordinates);break;case"MultiPoint":b=this.readMultiPoint(a.coordinates);break;case"LineString":b=this.readLineString(a.coordinates);break;case"MultiLineString":b=this.readMultiLineString(a.coordinates);break;case"Polygon":b=this.readPolygon(a.coordinates);break;case"MultiPolygon":b=this.readMultiPolygon(a.coordinates);break;case"GeometryCollection":for(e=[],f=0;fd)&&(d=a),(null===c||c>a)&&(c=a),this.data()[this.data().length]=a},this.insertAt=function(a,b){(null===d||b>d)&&(d=b),(null===c||c>b)&&(c=b),this.data()[a]=b},this.scalarRange=function(){return null===e||null===f?[c,d]:[e,f]},this.setScalarRange=function(a,b){e=a,f=b},this},inherit(b.sourceDataSf,b.sourceData),b.sourceDataDf=function(a){"use strict";return this instanceof b.sourceDataDf?(b.sourceData.call(this,a),this.addAttribute(b.vertexAttributeKeys.Scalar,b.GL.FLOAT,4,0,4,1,!1),this.pushBack=function(a){this.data()[this.data().length]=a},this.insertAt=function(a,b){this.data()[a]=b},this):new b.sourceDataDf(a)},inherit(b.sourceDataDf,b.sourceData),b.geometryData=function(){"use strict";if(!(this instanceof b.geometryData))return new b.geometryData;b.data.call(this);var a="",c=[],d=[],e=[0,0,0,0,0,0],f=b.timestamp(),g=b.timestamp();return this.type=function(){return b.data.geometry},this.name=function(){return a},this.setName=function(b){a=b},this.addSource=function(a,c){return void 0!==c&&a.setName(c),-1===d.indexOf(a)?(d.push(a),a.hasKey(b.vertexAttributeKeys.Position)&&g.modified(),!0):!1},this.source=function(a){return af.getMTime()&&this.computeBounds(),e},this.boundsDirty=function(a){return a&&g.modified(),g.getMTime()>f.getMTime()},this.resetBounds=function(){e[0]=0,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=0},this.setBounds=function(a,b,c,d,g,h){return e[0]=a,e[1]=b,e[2]=c,e[3]=d,e[4]=g,e[5]=h,f.modified(),!0},this.computeBounds=function(){if(g.getMTime()>f.getMTime()){var a,c,d,h,i,j,k=b.vertexAttributeKeys.Position,l=this.sourceData(k),m=l.data(),n=l.attributeNumberOfComponents(k),o=l.attributeStride(k),p=l.attributeOffset(k),q=l.sizeOfAttributeDataType(k),r=m.length,s=null;for(o/=q,p/=q,this.resetBounds(),a=0;n>a;a+=1){for(c=2*a,d=2*a+1,h=i=r?e[d]=m[p+a]:0,j=p+o+a;r>j;j+=o)s=m[j],s>h&&(h=s),i>s&&(i=s);e[c]=i,e[d]=h}f.modified()}},this.findClosestVertex=function(a){var c,d,e,f,g,h,i,j=b.vertexAttributeKeys.Position,k=this.sourceData(j),l=k.sizeOfAttributeDataType(j),m=k.attributeNumberOfComponents(j),n=k.data(),o=k.attributeStride(j)/l,p=k.attributeOffset(j)/l,q=Number.MAX_VALUE,r=null;for(3!==m&&console.log("[warning] Find closest vertex assumes threecomponent vertex "),a.z||(a={x:a.x,y:a.y,z:0}),c=p,i=0;ch&&(q=h,r=i);return r},this.getPosition=function(a){var c=b.vertexAttributeKeys.Position,d=this.sourceData(c),e=d.sizeOfAttributeDataType(c),f=d.attributeNumberOfComponents(c),g=d.data(),h=d.attributeStride(c)/e,i=d.attributeOffset(c)/e;return 3!==f&&console.log("[warning] getPosition assumes three component data"),[g[i+a*h],g[i+a*h+1],g[i+a*h+2]]},this.getScalar=function(a){var c,d,e,f,g=b.vertexAttributeKeys.Scalar,h=this.sourceData(g);return h?(c=h.sizeOfAttributeDataType(g),d=h.data(),e=h.attributeStride(g)/c,f=h.attributeOffset(g)/c,a*e+f>=d.length&&console.log("access out of bounds in getScalar"),d[a*e+f]):null},this},inherit(b.geometryData,b.data),b.mapper=function(a){"use strict";function c(a){if(g){a&&(l=a.m_context);var c,d,e,f,m,n,o,p=g.numberOfSources(),q=null;for(c=0;p>c;c+=1){for(q=l.createBuffer(),l.bindBuffer(b.GL.ARRAY_BUFFER,q),o=g.source(c).data(),o instanceof Float32Array||(o=new Float32Array(o)),l.bufferData(b.GL.ARRAY_BUFFER,o,j?b.GL.DYNAMIC_DRAW:b.GL.STATIC_DRAW),f=g.source(c).keys(),m=[],d=0;de;e+=1)q=l.createBuffer(),l.bindBuffer(b.GL.ARRAY_BUFFER,q),l.bufferData(b.GL.ARRAY_BUFFER,g.primitive(e).indices(),b.GL.STATIC_DRAW),h[c]=q,c+=1;k.modified()}}function d(a){i={},h=[]}function e(a){m.deleteVertexBufferObjects(a),d(a),c(a)}if(!(this instanceof b.mapper))return new b.mapper(a);b.boundingObject.call(this),a=a||{};var f=[0,1,1],g=null,h=[],i={},j=void 0===a.dynamicDraw?!1:a.dynamicDraw,k=b.timestamp(),l=null,m=this;return this.deleteVertexBufferObjects=function(a){var b,c=l;if(a&&(c=a.m_context),c)for(b=0;ba.getMTime()&&(c=g.bounds(),this.setBounds(c[0],c[1],c[2],c[3],c[4],c[5]),a.modified())},this.color=function(){return f},this.setColor=function(a,b,c){f[0]=a,f[1]=b,f[2]=c,this.modified()},this.geometryData=function(){return g},this.setGeometryData=function(a){g!==a&&(g=a,this.modified(),this.boundsDirtyTimestamp().modified())},this.updateSourceBuffer=function(a,c,d){if(d&&(l=d.m_context),!l)return!1;for(var e=-1,f=0;fe||e>=h.length?!1:(c||(c=g.source(f).dataToFloat32Array()),l.bindBuffer(b.GL.ARRAY_BUFFER,h[e]),c instanceof Float32Array?l.bufferSubData(b.GL.ARRAY_BUFFER,0,c):l.bufferSubData(b.GL.ARRAY_BUFFER,0,new Float32Array(c)),!0)},this.getSourceBuffer=function(a){ +var b=g.sourceByName(a);return b?b.dataToFloat32Array():new Float32Array},this.render=function(a,c){(this.getMTime()>k.getMTime()||a.m_contextChanged)&&e(a),l=a.m_context,l.vertexAttrib3fv(b.vertexAttributeKeys.Color,this.color());var d,f=0,j=0,m=null,n=null;for(d in i)if(i.hasOwnProperty(d)){for(l.bindBuffer(b.GL.ARRAY_BUFFER,h[f]),j=0;jj;j+=1,f+=1)if(n=g.primitive(j),n.numberOfIndices()){switch(l.bindBuffer(b.GL.ARRAY_BUFFER,h[f]),n.primitiveType()){case b.GL.POINTS:l.drawArrays(b.GL.POINTS,0,n.numberOfIndices());break;case b.GL.LINES:l.drawArrays(b.GL.LINES,0,n.numberOfIndices());break;case b.GL.LINE_STRIP:l.drawArrays(b.GL.LINE_STRIP,0,n.numberOfIndices());break;case b.GL.TRIANGLES:l.drawArrays(b.GL.TRIANGLES,0,n.numberOfIndices());break;case b.GL.TRIANGLE_STRIP:l.drawArrays(b.GL.TRIANGLE_STRIP,0,n.numberOfIndices())}l.bindBuffer(b.GL.ARRAY_BUFFER,null)}c||this.undoBindVertexData(a)},this.undoBindVertexData=function(a){var b,c;for(b in i)if(i.hasOwnProperty(b))for(c=0;c0?d[0]:null},this.setGeometryData=function(a){(1!==d.length||d[0]!==a)&&(d=[],d.push(a),this.modified())},this.geometryDataArray=function(){return d},this.setGeometryDataArray=function(a){if(a instanceof Array){if(d!==a)return d=[],d=a,this.modified(),!0}else console.log("[error] Requies array of geometry data");return!1},this.computeBounds=function(){if(null===d||void 0===d)return void this.resetBounds();var a=this.computeBoundsTimestamp(),b=this.boundsDirtyTimestamp(),c=this.bounds(),e=null,f=null;if(b.getMTime()>a.getMTime()){for(f=0;fe[0]&&(c[0]=e[0]),c[1]e[2]&&(c[2]=e[2]),c[3]e[4]&&(c[4]=e[4]),c[5]a.getMTime()){for(f=0;f0&&c.m_resetScene&&(c.resetCamera(),c.m_resetScene=!1),a=0;a=0&&g.push([f.material().binNumber(),f]);for(g.sort(function(a,b){return a[0]-b[0]}),a=0;ae[1]?e[0]>e[2]?e[0]/2:e[2]/2:e[1]>e[2]?e[1]/2:e[2]/2,h=g>=1?2*Math.atan(Math.tan(.5*h)/g):2*Math.atan(Math.tan(.5*h)*g),i=f/Math.sin(.5*h),j=c.m_camera.viewUpDirection(),Math.abs(vec3.dot(j,a))>.999&&c.m_camera.setViewUpDirection(-j[2],j[0],j[1]),c.m_camera.setFocalPoint(d[0],d[1],d[2]),c.m_camera.setPosition(d[0]+i*-a[0],d[1]+i*-a[1],d[2]+i*-a[2]),c.resetCameraClippingRange(b)},this.hasValidBounds=function(a){return a[0]===Number.MAX_VALUE||a[1]===-Number.MAX_VALUE||a[2]===Number.MAX_VALUE||a[3]===-Number.MAX_VALUE||a[4]===Number.MAX_VALUE||a[5]===-Number.MAX_VALUE?!1:!0},this.resetCameraClippingRange=function(a){if("undefined"==typeof a&&(c.m_camera.computeBounds(),a=c.m_camera.bounds()),c.hasValidBounds(a)){var b=c.m_camera.viewPlaneNormal(),d=c.m_camera.position(),e=-b[0],f=-b[1],g=-b[2],h=-(e*d[0]+f*d[1]+g*d[2]),i=vec2.create(),j=null,k=null,l=null,m=null;if(c.m_resetClippingRange){for(i[0]=e*a[0]+f*a[2]+g*a[4]+h,i[1]=1e-18,m=0;2>m;m+=1)for(l=0;2>l;l+=1)for(k=0;2>k;k+=1)j=e*a[k]+f*a[2+l]+g*a[4+m]+h,i[0]=ji[1]?j:i[1];i[0]<0&&(i[0]=0),i[0]=.99*i[0]-.5*(i[1]-i[0]),i[1]=1.01*i[1]+.5*(i[1]-i[0]),i[0]=i[0]>=i[1]?.01*i[1]:i[0],c.m_nearClippingPlaneTolerance||(c.m_nearClippingPlaneTolerance=.01,c.m_depthBits&&c.m_depthBits>16&&(c.m_nearClippingPlaneTolerance=.001)),i[0]a||0>b||0>=d||0>=e)return void console.log("[error] Invalid position and resize values",a,b,d,e);if(c.m_resizable&&(c.m_width=d,c.m_height=e,c.m_camera.setViewAspect(d/e),c.m_camera.setParallelExtents({width:d,height:e}),c.modified()),c.m_renderPasses)for(f=0;ff||0===j[b].width()||j[b].height()>g||0===j[b].height())&&j[b].resize(d,e,f,g);return!0}catch(c){}return k||console("[ERROR] Unable to initialize WebGL. Your browser may not support it."),!1},this.context=function(){return k},this._cleanup=function(a){var d;for(d=0;dt?(g.x=0,a=!0):g.x=x.x,x.y<0||x.y>u?(g.y=0,a=!0):g.y=x.y,a!==!0?(i=w.focalPoint(),k=vec4.fromValues(i[0],i[1],i[2],1),j=v.worldToDisplay(k,w.viewMatrix(),w.projectionMatrix(),t,u),l=vec4.fromValues(g.x,g.y,j[2],1),m=vec4.fromValues(h.x,h.y,j[2],1),n=v.displayToWorld(l,w.viewMatrix(),w.projectionMatrix(),t,u),o=v.displayToWorld(m,w.viewMatrix(),w.projectionMatrix(),t,u),p=n[0]-o[0],q=n[1]-o[1],r=n[2]-o[2],f&&(w.pan(-p,-q,-r),c.viewer().render()),d&&(w.rotate(h.x-g.x,h.y-g.y),v.resetCameraClippingRange(),c.viewer().render()),e&&(s=2*(g.y-h.y)/u,s>0?w.zoom(1-Math.abs(s)):w.zoom(1+Math.abs(s)),v.resetCameraClippingRange(),c.viewer().render()),h.x=g.x,h.y=g.y,!1):void 0},this.handleMouseDown=function(a){var b;return 0===a.button&&(d=!0),1===a.button&&(f=!0),2===a.button&&(e=!0),b=c.viewer().relMouseCoords(a),b.x<0?h.x=0:h.x=b.x,b.y<0?h.y=0:h.y=b.y,!1},this.handleMouseUp=function(a){return 0===a.button&&(d=!1),1===a.button&&(f=!1),2===a.button&&(e=!1),!1},this.handleMouseWheel=function(a){var b=c.viewer().renderWindow().activeRenderer(),d=b.camera();return a.originalEvent.wheelDelta<0?d.zoom(.9):d.zoom(1.1),b.resetCameraClippingRange(),c.viewer().render(),!0},this},inherit(b.trackballInteractorStyle,b.interactorStyle),b.viewer=function(a,c){"use strict";if(!(this instanceof b.viewer))return new b.viewer(a,c);b.object.call(this);var d=this,e=a,f=!0,g=null,h=b.renderer(c),i=b.renderWindow(e);return this.canvas=function(){return e},this.renderWindow=function(){return i},this.init=function(){null!==i?i._setup():console.log("[ERROR] No render window attached")},this.exit=function(a){null!==i?i._cleanup(a):console.log("[ERROR] No render window attached")},this.interactorStyle=function(){return g},this.setInteractorStyle=function(a){a!==g&&(g=a,g.setViewer(this),this.modified())},this.handleMouseDown=function(a){if(f===!0){var c=$.event.fix(a||window.event);2===a.button&&c.preventDefault(),c.state="down",c.type=b.event.mousePress,$(d).trigger(c)}return!0},this.handleMouseUp=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.state="up",c.type=b.event.mouseRelease,$(d).trigger(c)}return!0},this.handleMouseMove=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.mouseMove,$(d).trigger(c)}return!0},this.handleMouseWheel=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.mouseWheel,$(d).trigger(c)}return!0},this.handleMouseOut=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.mouseOut,$(d).trigger(c)}return!0},this.handleKeyPress=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.keyPress,$(d).trigger(c)}return!0},this.handleContextMenu=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.contextMenu,$(d).trigger(c)}return!1},this.handleClick=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.click,$(d).trigger(c)}return!1},this.handleDoubleClick=function(a){if(f===!0){var c=$.event.fix(a||window.event);c.preventDefault(),c.type=b.event.dblClick,$(d).trigger(c)}return!1},this.relMouseCoords=function(a){if(void 0===a.pageX||void 0===a.pageY)throw"Missing attributes pageX and pageY on the event";var b=0,c=0,d=0,f=0,g=e;do b+=g.offsetLeft-g.scrollLeft,c+=g.offsetTop-g.scrollTop,g=g.offsetParent;while(g);return d=a.pageX-b,f=a.pageY-c,{x:d,y:f}},this.render=function(){i.render()},this.bindEventHandlers=function(){$(e).on("mousedown",this.handleMouseDown),$(e).on("mouseup",this.handleMouseUp),$(e).on("mousemove",this.handleMouseMove),$(e).on("mousewheel",this.handleMouseWheel),$(e).on("contextmenu",this.handleContextMenu)},this.unbindEventHandlers=function(){$(e).off("mousedown",this.handleMouseDown),$(e).off("mouseup",this.handleMouseUp),$(e).off("mousemove",this.handleMouseMove),$(e).off("mousewheel",this.handleMouseWheel),$(e).off("contextmenu",this.handleContextMenu)},this._init=function(){this.bindEventHandlers(),i.addRenderer(h)},this._init(),this},inherit(b.viewer,b.object),b.shader=function(a){"use strict";if(!(this instanceof b.shader))return new b.shader(a);b.object.call(this);var c=[],d=a,e="";this._getContextEntry=function(a){var d,e,f=a.m_context;for(d=0;d=c&&a.splice(c,a.length-c),h},b.clearCachedShaders=function(b){for(var c=a.length-1;c>=0;c-=1)(null===b||void 0===b||a[c].context===b)&&a.splice(c,1)}}();var d=function(){"use strict";var a=".",b=document.getElementsByTagName("script");if(b.length>0){var c=b.length-1,d=b[c];c=d.src.lastIndexOf("/"),a=d.src.substring(0,c)}return function(){return a}}();return b.shaderProgram=function(){"use strict";if(!(this instanceof b.shaderProgram))return new b.shaderProgram;b.materialAttribute.call(this,b.materialAttributeType.ShaderProgram);var a=this,c=0,e=b.timestamp(),f=b.timestamp(),g=[],h=[],i={},j={},k={};return this.loadFromFile=function(c,d){var e,f=!1;return $.ajax({url:d,type:"GET",dataType:"text",async:!1,success:function(d){e=b.shader(c),e.setShaderSource(d),a.addShader(e),f=!0}}),f},this.loadShader=function(a,b){return this.loadFromFile(a,d()+"/shaders/"+b)},this.queryUniformLocation=function(a,b){return a.m_context.getUniformLocation(c,b)},this.queryAttributeLocation=function(a,b){return a.m_context.getAttribLocation(c,b)},this.addShader=function(b){if(g.indexOf(b)>-1)return!1;var c;for(c=g.length-2;c>=0;c-=1)g[c].shaderType()===b.shaderType()&&g.splice(c,1);return g.push(b),a.modified(),!0},this.addUniform=function(b){return h.indexOf(b)>-1?!1:(h.push(b),a.modified(),!0)},this.addVertexAttribute=function(b,c){i[c]=b,a.modified()},this.uniformLocation=function(a){return j[a]},this.attributeLocation=function(a){return k[a]},this.uniform=function(a){var b;for(b=0;b=this.getMTime())){for(a._setup(b),d=0;dc.getMTime()&&this.setup(d),a(d),d.m_context.bindTexture(b.GL.TEXTURE_2D,this.m_textureHandle)},this.undoBind=function(a){a.m_context.bindTexture(b.GL.TEXTURE_2D,null)},this.image=function(){return this.m_image},this.setImage=function(a){return null!==a?(this.m_image=a,this.updateDimensions(),this.modified(),!0):!1},this.nearestPixel=function(){return this.m_nearestPixel},this.setNearestPixel=function(a){return a=a?!0:!1,a!==this.m_nearestPixel?(this.m_nearestPixel=a,this.modified(),!0):!1},this.textureUnit=function(){return this.m_textureUnit},this.setTextureUnit=function(a){return this.m_textureUnit===a?!1:(this.m_textureUnit=a,this.modified(),!0)},this.width=function(){return this.m_width},this.setWidth=function(a){return d.m_width!==a?(d.m_width=a,d.modified(),!0):!1},this.height=function(){return d.m_height},this.setHeight=function(a){return d.m_height!==a?(d.m_height=a,d.modified(),!0):!1},this.depth=function(){return this.m_depth},this.setDepth=function(a){return null===this.m_image?!1:(this.m_depth=a,this.modified(),!0)},this.textureHandle=function(){return this.m_textureHandle},this.internalFormat=function(){return this.m_internalFormat},this.setInternalFormat=function(a){return this.m_internalFormat!==a?(this.m_internalFormat=a,this.modified(),!0):!1},this.pixelFormat=function(){return this.m_pixelFormat},this.setPixelFormat=function(a){return null===this.m_image?!1:(this.m_pixelFormat=a,this.modified(),!0)},this.pixelDataType=function(){return this.m_pixelDataType},this.setPixelDataType=function(a){return null===this.m_image?!1:(this.m_pixelDataType=a,this.modified(),!0)},this.computeInternalFormatUsingImage=function(){this.m_internalFormat=b.GL.RGBA,this.m_pixelFormat=b.GL.RGBA,this.m_pixelDataType=b.GL.UNSIGNED_BYTE},this.updateDimensions=function(){null!==this.m_image&&(this.m_width=this.m_image.width,this.m_height=this.m_image.height,this.m_depth=0)},this},inherit(b.texture,b.materialAttribute),b.lookupTable=function(){"use strict";if(!(this instanceof b.lookupTable))return new b.lookupTable;b.texture.call(this);var a=b.timestamp(),c=[0,0];return this.m_colorTable=[.07514311,.468049805,1,1,.247872569,.498782363,1,1,.339526309,.528909511,1,1,.409505078,.558608486,1,1,.468487184,.588057293,1,1,.520796675,.617435078,1,1,.568724526,.646924167,1,1,.613686735,.676713218,1,1,.656658579,.707001303,1,1,.698372844,.738002964,1,1,.739424025,.769954435,1,1,.780330104,.803121429,1,1,.821573924,.837809045,1,1,.863634967,.874374691,1,1,.907017747,.913245283,1,1,.936129275,.938743558,.983038586,1,.943467973,.943498599,.943398095,1,.990146732,.928791426,.917447482,1,1,.88332677,.861943246,1,1,.833985467,.803839606,1,1,.788626485,.750707739,1,1,.746206642,.701389973,1,1,.70590052,.654994046,1,1,.667019783,.610806959,1,1,.6289553,.568237474,1,1,.591130233,.526775617,1,1,.552955184,.485962266,1,1,.513776083,.445364274,1,1,.472800903,.404551679,1,1,.428977855,.363073592,1,1,.380759558,.320428137,1,.961891484,.313155629,.265499262,1,.916482116,.236630659,.209939162,1].map(function(a){return 255*a}),this.setup=function(c){0===this.textureUnit()?c.m_context.activeTexture(b.GL.TEXTURE0):1===this.textureUnit()&&c.m_context.activeTexture(b.GL.TEXTURE1),c.m_context.deleteTexture(this.m_textureHandle),this.m_textureHandle=c.m_context.createTexture(),c.m_context.bindTexture(b.GL.TEXTURE_2D,this.m_textureHandle),c.m_context.texParameteri(b.GL.TEXTURE_2D,b.GL.TEXTURE_MIN_FILTER,b.GL.LINEAR),c.m_context.texParameteri(b.GL.TEXTURE_2D,b.GL.TEXTURE_MAG_FILTER,b.GL.LINEAR),c.m_context.texParameteri(b.GL.TEXTURE_2D,b.GL.TEXTURE_WRAP_S,b.GL.CLAMP_TO_EDGE),c.m_context.texParameteri(b.GL.TEXTURE_2D,b.GL.TEXTURE_WRAP_T,b.GL.CLAMP_TO_EDGE),c.m_context.pixelStorei(b.GL.UNPACK_ALIGNMENT,1),this.m_width=this.m_colorTable.length/4,this.m_height=1,this.m_depth=0,c.m_context.texImage2D(b.GL.TEXTURE_2D,0,b.GL.RGBA,this.m_width,this.m_height,this.m_depth,b.GL.RGBA,b.GL.UNSIGNED_BYTE,new Uint8Array(this.m_colorTable)),c.m_context.bindTexture(b.GL.TEXTURE_2D,null),a.modified()},this.colorTable=function(){return this.m_colorTable},this.setColorTable=function(a){return this.m_colorTable===a?!1:(this.m_colorTable=a,this.modified(),!0)},this.range=function(){return c},this.setRange=function(a){return c===a?!1:(c=a,this.modified(),!0)},this.updateRange=function(a){a instanceof Array||console.log("[error] Invalid data type for range. Requires array [min,max]"),a[0]c[1]&&(c[1]=a[1],this.modified())},this},inherit(b.lookupTable,b.texture),b.uniform=function(a,c){"use strict";if(!(this instanceof b.uniform))return new b.uniform(a,c);this.getTypeNumberOfComponents=function(a){switch(a){case b.GL.FLOAT:case b.GL.INT:case b.GL.BOOL:return 1;case b.GL.FLOAT_VEC2:case b.GL.INT_VEC2:case b.GL.BOOL_VEC2:return 2;case b.GL.FLOAT_VEC3:case b.GL.INT_VEC3:case b.GL.BOOL_VEC3:return 3;case b.GL.FLOAT_VEC4:case b.GL.INT_VEC4:case b.GL.BOOL_VEC4:return 4;case b.GL.FLOAT_MAT3:return 9;case b.GL.FLOAT_MAT4:return 16;default:return 0}};var d=a,e=c,f=[];return f.length=this.getTypeNumberOfComponents(d),this.name=function(){return e},this.type=function(){return d},this.get=function(){return f},this.set=function(a){var b=0,c=f.length;if(1!==c)for(b=0;c>b;b+=1)f[b]=a[b];else f[0]=a},this.callGL=function(a,c){switch(d){case b.GL.BOOL:case b.GL.INT:a.m_context.uniform1iv(c,f);break;case b.GL.FLOAT:a.m_context.uniform1fv(c,f);break;case b.GL.BOOL_VEC2:case b.GL.INT_VEC2:a.m_context.uniform2iv(c,f);break;case b.GL.FLOAT_VEC2:a.m_context.uniform2fv(c,f);break;case b.GL.BOOL_VEC3:case b.GL.INT_VEC3:a.m_context.uniform3iv(c,f);break;case b.GL.FLOAT_VEC3:a.m_context.uniform3fv(c,f);break;case b.GL.BOOL_VEC4:case b.GL.INT_VEC4:a.m_context.uniform4iv(c,f);break;case b.GL.FLOAT_VEC4:a.m_context.uniform4fv(c,f);break;case b.GL.FLOAT_MAT3:a.m_context.uniformMatrix3fv(c,b.GL.FALSE,f);break;case b.GL.FLOAT_MAT4:a.m_context.uniformMatrix4fv(c,b.GL.FALSE,f)}},this.update=function(a,b){},this},b.modelViewUniform=function(a){"use strict";return this instanceof b.modelViewUniform?(a||(a="modelViewMatrix"),b.uniform.call(this,b.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.update=function(a,b){this.set(a.m_modelViewMatrix)},this):new b.modelViewUniform(a)},inherit(b.modelViewUniform,b.uniform),b.modelViewOriginUniform=function(a,c){"use strict";if(!(this instanceof b.modelViewOriginUniform))return new b.modelViewOriginUniform(a,c);a||(a="modelViewMatrix"),c=c||[0,0,0];var d=[c[0],c[1],c[2]||0];return b.uniform.call(this,b.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.setOrigin=function(a){a=a||[0,0,0],d=[a[0],a[1],a[2]||0]},this.update=function(a,b){var c=a.m_modelViewMatrix;if(a.m_modelViewAlignment){var e=a.m_modelViewAlignment;c=c.slice?c.slice():Array.prototype.slice.call(c),c[12]=Math.round(c[12]/e.roundx)*e.roundx+e.dx,c[13]=Math.round(c[13]/e.roundy)*e.roundy+e.dy}c=mat4.translate(mat4.create(),c,d),this.set(c)},this},inherit(b.modelViewOriginUniform,b.uniform),b.projectionUniform=function(a){"use strict";return this instanceof b.projectionUniform?(a||(a="projectionMatrix"),b.uniform.call(this,b.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.update=function(a,b){this.set(a.m_projectionMatrix)},this):new b.projectionUniform(a)},inherit(b.projectionUniform,b.uniform),b.floatUniform=function(a,c){"use strict";return this instanceof b.floatUniform?(a||(a="floatUniform"),c=void 0===c?1:c,b.uniform.call(this,b.GL.FLOAT,a),void this.set(c)):new b.floatUniform(a,c)},inherit(b.floatUniform,b.uniform),b.normalMatrixUniform=function(a){"use strict";return this instanceof b.normalMatrixUniform?(a||(a="normalMatrix"),b.uniform.call(this,b.GL.FLOAT_MAT4,a),this.set(mat4.create()),this.update=function(a,b){this.set(a.m_normalMatrix)},this):new b.normalMatrixUniform(a)},inherit(b.normalMatrixUniform,b.uniform),b.vertexAttributeKeys={Position:0,Normal:1,TextureCoordinate:2,Color:3,Scalar:4,CountAttributeIndex:5},b.vertexAttributeKeysIndexed={Zero:0,One:1,Two:2,Three:3,Four:4,Five:5,Six:6,Seven:7,Eight:8,Nine:9},b.vertexAttribute=function(a){"use strict";if(!(this instanceof b.vertexAttribute))return new b.vertexAttribute(a);var c=a;this.name=function(){return c},this.bindVertexData=function(a,b){var d=a.m_mapper.geometryData(),e=d.sourceData(b),f=a.m_material.shaderProgram();a.m_context.vertexAttribPointer(f.attributeLocation(c),e.attributeNumberOfComponents(b),e.attributeDataType(b),e.normalized(b),e.attributeStride(b),e.attributeOffset(b)),a.m_context.enableVertexAttribArray(f.attributeLocation(c))},this.undoBindVertexData=function(a,b){b=b;var d=a.m_material.shaderProgram();a.m_context.disableVertexAttribArray(d.attributeLocation(c))}},b.source=function(){"use strict";return this instanceof b.source?(b.object.call(this),this.create=function(){},this):new b.source},inherit(b.source,b.object),b.planeSource=function(){"use strict";if(!(this instanceof b.planeSource))return new b.planeSource;b.source.call(this);var a=[0,0,0],c=[1,0,0],d=[0,1,0],e=[0,0,1],f=1,g=1,h=null;this.setOrigin=function(b,c,d){a[0]=b,a[1]=c,a[2]=d},this.setPoint1=function(a,b,d){c[0]=a,c[1]=b,c[2]=d},this.setPoint2=function(a,b,c){d[0]=a,d[1]=b,d[2]=c},this.create=function(){h=new b.geometryData;var i,j,k,l,m,n=[],o=[],p=[],q=[],r=[],s=0,t=0,u=0,v=0,w=[],x=[],y=[],z=[],A=[],B=null,C=null,D=null;for(n.length=3,o.length=2,p.length=3,q.length=3,r.length=3,i=0;3>i;i+=1)p[i]=c[i]-a[i],q[i]=d[i]-a[i];for(l=(f+1)*(g+1),w.length=3*l,x.length=3*l,z.length=2*l,A.length=l,i=0;g+1>i;i+=1)for(o[1]=i/g,j=0;f+1>j;j+=1){for(o[0]=j/f,k=0;3>k;k+=1)n[k]=a[k]+o[0]*p[k]+o[1]*q[k];w[s++]=n[0],w[s++]=n[1],w[s++]=n[2],y[u++]=1,y[u++]=1,y[u++]=1,x[t++]=e[0],x[t++]=e[1],x[t++]=e[2],z[v++]=o[0],z[v++]=o[1]}for(i=0;g>i;i+=1)for(j=0;f>j;j+=1)r[0]=j+i*(f+1),r[1]=r[0]+1,r[2]=r[0]+f+2,r[3]=r[0]+f+1;for(i=0;l>i;i+=1)A[i]=i;return B=new b.triangleStrip,B.setIndices(A),C=b.sourceDataP3fv(),C.pushBack(w),D=b.sourceDataC3fv(),D.pushBack(y),m=b.sourceDataT2fv(),m.pushBack(z),h.addSource(C),h.addSource(D),h.addSource(m),h.addPrimitive(B),h}},inherit(b.planeSource,b.source),b.pointSource=function(){"use strict";if(!(this instanceof b.pointSource))return new b.pointSource;b.source.call(this);var a=this,c=[],d=[],e=[],f=[],g=null;this.getPositions=function(){return c},this.setPositions=function(b){b instanceof Array?c=b:console.log("[ERROR] Invalid data type for positions. Array is required."),a.modified()},this.getColors=function(){return d},this.setColors=function(b){b instanceof Array?d=b:console.log("[ERROR] Invalid data type for colors. Array is required."),a.modified()},this.getSize=function(){return f},this.setSize=function(a){f=a,this.modified()},this.setTextureCoordinates=function(b){b instanceof Array?e=b:console.log("[ERROR] Invalid data type for texture coordinates. Array is required."),a.modified()},this.create=function(){if(g=new b.geometryData,c.length%3!==0)return void console.log("[ERROR] Invalid length of the points array");var a,h,i,j,k,l=c.length/3,m=0,n=[];for(n.length=l,m=0;l>m;m+=1)n[m]=m;if(k=b.sourceDataDf(),l!==f.length)for(m=0;l>m;m+=1)k.pushBack(f);else k.setData(f);return g.addSource(k),a=new b.points,a.setIndices(n),h=b.sourceDataP3fv(),h.pushBack(c),g.addSource(h),d.length>0&&d.length===c.length?(i=b.sourceDataC3fv(),i.pushBack(d),g.addSource(i)):d.length>0&&d.length!==c.length&&console.log("[ERROR] Number of colors are different than number of points"),e.length>0&&e.length===c.length?(j=b.sourceDataT2fv(),j.pushBack(e),g.addSource(j)):e.length>0&&e.length/2!==c.length/3&&console.log("[ERROR] Number of texture coordinates are different than number of points"),g.addPrimitive(a),g}},inherit(b.pointSource,b.source),b.lineSource=function(a,c){"use strict";if(!(this instanceof b.lineSource))return new b.lineSource;b.source.call(this);var d=a,e=c;this.setPositions=function(a){return a instanceof Array?(d=a,this.modified(),!0):(console.log("[ERROR] Invalid data type for positions. Array is required."),!1)},this.setColors=function(a){return a instanceof Array?(e=a,this.modified(),!0):(console.log("[ERROR] Invalid data type for colors. Array is required."),!1)},this.create=function(){if(!d)return void console.log("[error] Invalid positions");if(d.length%3!==0)return void console.log("[error] Line source requires 3d points");if(d.length%3!==0)return void console.log("[ERROR] Invalid length of the points array");var a,c,f,g,h=new b.geometryData,i=d.length/3,j=[];for(j.length=i,a=0;i>a;a+=1)j[a]=a;return c=new b.lines,c.setIndices(j),f=b.sourceDataP3fv(),f.pushBack(d),h.addSource(f),e&&e.length>0&&e.length===d.length?(g=b.sourceDataC3fv(),g.pushBack(e),h.addSource(g)):e&&e.length>0&&e.length!==d.length&&console.log("[error] Number of colors are different than number of points"),h.addPrimitive(c),h}},inherit(b.lineSource,b.source),b.utils=function(){"use strict";return this instanceof b.utils?(b.object.call(this),this):new b.utils},inherit(b.utils,b.object),b.utils.computePowerOfTwo=function(a,b){"use strict";for(b=b||1;a>b;)b*=2;return b},b.utils.createTextureVertexShader=function(a){"use strict";var c=["attribute vec3 vertexPosition;","attribute vec3 textureCoord;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","varying highp vec3 iTextureCoord;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);"," iTextureCoord = textureCoord;","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,c)},b.utils.createTextureFragmentShader=function(a){"use strict";var c=["varying highp vec3 iTextureCoord;","uniform sampler2D sampler2d;","uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4(texture2D(sampler2d, vec2(iTextureCoord.s, iTextureCoord.t)).xyz, opacity);","}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,c)},b.utils.createRgbaTextureFragmentShader=function(a){"use strict";var c=["varying highp vec3 iTextureCoord;","uniform sampler2D sampler2d;","uniform mediump float opacity;","void main(void) {"," mediump vec4 color = vec4(texture2D(sampler2d, vec2(iTextureCoord.s, iTextureCoord.t)).xyzw);"," color.w *= opacity;"," gl_FragColor = color;","}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,c)},b.utils.createVertexShader=function(a){"use strict";var c=["attribute vec3 vertexPosition;","attribute vec3 vertexColor;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","varying mediump vec3 iVertexColor;","varying highp vec3 iTextureCoord;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);"," iVertexColor = vertexColor;","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,c)},b.utils.createPointVertexShader=function(a){"use strict";var c=["attribute vec3 vertexPosition;","attribute vec3 vertexColor;","attribute float vertexSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","varying mediump vec3 iVertexColor;","varying highp vec3 iTextureCoord;","void main(void)","{","gl_PointSize = vertexSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);"," iVertexColor = vertexColor;","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,c)},b.utils.createVertexShaderSolidColor=function(a){"use strict";var c=["attribute vec3 vertexPosition;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,c)},b.utils.createVertexShaderColorMap=function(a,c,d){"use strict";c=c,d=d;var e=["attribute vec3 vertexPosition;","attribute float vertexScalar;","uniform mediump float pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float lutMin;","uniform float lutMax;","varying mediump float iVertexScalar;","void main(void)","{","gl_PointSize = pointSize;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);","iVertexScalar = (vertexScalar-lutMin)/(lutMax-lutMin);","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,e)},b.utils.createFragmentShader=function(a){"use strict";var c=["varying mediump vec3 iVertexColor;","uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4(iVertexColor, opacity);","}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,c)},b.utils.createPhongVertexShader=function(a){"use strict";var c=["attribute highp vec3 vertexPosition;","attribute mediump vec3 vertexNormal;","attribute mediump vec3 vertexColor;","uniform highp mat4 projectionMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 normalMatrix;","varying highp vec4 varPosition;","varying mediump vec3 varNormal;","varying mediump vec3 varVertexColor;","void main(void)","{","varPosition = modelViewMatrix * vec4(vertexPosition, 1.0);","gl_Position = projectionMatrix * varPosition;","varNormal = vec3(normalMatrix * vec4(vertexNormal, 0.0));","varVertexColor = vertexColor;","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,c)},b.utils.createPhongFragmentShader=function(a){"use strict";var c=["uniform mediump float opacity;","precision mediump float;","varying vec3 varNormal;","varying vec4 varPosition;","varying mediump vec3 varVertexColor;","const vec3 lightPos = vec3(0.0, 0.0,10000.0);","const vec3 ambientColor = vec3(0.01, 0.01, 0.01);","const vec3 specColor = vec3(0.0, 0.0, 0.0);","void main() {","vec3 normal = normalize(varNormal);","vec3 lightDir = normalize(lightPos);","vec3 reflectDir = -reflect(lightDir, normal);","vec3 viewDir = normalize(-varPosition.xyz);","float lambertian = max(dot(lightDir, normal), 0.0);","vec3 color = vec3(0.0);","if(lambertian > 0.0) {"," color = lambertian * varVertexColor;","}","gl_FragColor = vec4(color * opacity, 1.0 - opacity);","}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,c)},b.utils.createFragmentShaderSolidColor=function(a,c){"use strict";var d=["uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4("+c[0]+","+c[1]+","+c[2]+", opacity);","}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,d)},b.utils.createFragmentShaderColorMap=function(a){"use strict";var c=["varying mediump float iVertexScalar;","uniform sampler2D sampler2d;","uniform mediump float opacity;","void main(void) {","gl_FragColor = vec4(texture2D(sampler2d, vec2(iVertexScalar, 0.0)).xyz, opacity);","}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,c)},b.utils.createPointSpritesVertexShader=function(a){"use strict";var c=["attribute vec3 vertexPosition;","attribute vec3 vertexColor;","uniform mediump vec2 pointSize;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float height;","varying mediump vec3 iVertexColor;","varying highp float iVertexScalar;","void main(void)","{","mediump float realPointSize = pointSize.y;","if (pointSize.x > pointSize.y) {"," realPointSize = pointSize.x;}","gl_PointSize = realPointSize ;","iVertexScalar = vertexPosition.z;","gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition.xy, height, 1.0);"," iVertexColor = vertexColor;","}"].join("\n");return b.getCachedShader(b.GL.VERTEX_SHADER,a,c)},b.utils.createPointSpritesFragmentShader=function(a){"use strict";var c=["varying mediump vec3 iVertexColor;","varying highp float iVertexScalar;","uniform sampler2D opacityLookup;","uniform highp float lutMin;","uniform highp float lutMax;","uniform sampler2D scalarsToColors;","uniform int useScalarsToColors;","uniform int useVertexColors;","uniform mediump vec2 pointSize;","uniform mediump float vertexColorWeight;","void main(void) {","mediump vec2 realTexCoord;","if (pointSize.x > pointSize.y) {"," realTexCoord = vec2(1.0, pointSize.y/pointSize.x) * gl_PointCoord;","} else {"," realTexCoord = vec2(pointSize.x/pointSize.y, 1.0) * gl_PointCoord;","}","highp float texOpacity = texture2D(opacityLookup, realTexCoord).w;","if (useScalarsToColors == 1) {"," gl_FragColor = vec4(texture2D(scalarsToColors, vec2((iVertexScalar - lutMin)/(lutMax - lutMin), 0.0)).xyz, texOpacity);","} else if (useVertexColors == 1) {"," gl_FragColor = vec4(iVertexColor, texOpacity);","} else {"," gl_FragColor = vec4(texture2D(opacityLookup, realTexCoord).xyz, texOpacity);","}}"].join("\n");return b.getCachedShader(b.GL.FRAGMENT_SHADER,a,c)},b.utils.createTextureMaterial=function(a,c){"use strict";var d,e=new b.material,f=new b.blend,g=new b.shaderProgram,h=b.utils.createTextureVertexShader(b.GL),i=null,j=new b.vertexAttribute("vertexPosition"),k=new b.vertexAttribute("textureCoord"),l=new b.floatUniform("pointSize",5),m=new b.projectionUniform("projectionMatrix"),n=new b.uniform(b.GL.INT,"sampler2d"),o=null;return d=void 0!==c?new b.modelViewOriginUniform("modelViewMatrix",c):new b.modelViewUniform("modelViewMatrix"),n.set(0),g.addVertexAttribute(j,b.vertexAttributeKeys.Position),g.addVertexAttribute(k,b.vertexAttributeKeys.TextureCoordinate),g.addUniform(l),g.addUniform(d),g.addUniform(m),i=a?b.utils.createRgbaTextureFragmentShader(b.GL):b.utils.createTextureFragmentShader(b.GL),o=new b.floatUniform("opacity",1),g.addUniform(o),g.addShader(i),g.addShader(h),e.addAttribute(g),e.addAttribute(f),e},b.utils.createGeometryMaterial=function(){"use strict";var a=new b.material,c=new b.shaderProgram,d=5,e=1,f=b.utils.createVertexShader(b.GL),g=b.utils.createFragmentShader(b.GL),h=new b.vertexAttribute("vertexPosition"),i=new b.vertexAttribute("vertexColor"),j=new b.floatUniform("pointSize",d),k=new b.floatUniform("opacity",e),l=new b.modelViewUniform("modelViewMatrix"),m=new b.projectionUniform("projectionMatrix");return c.addVertexAttribute(h,b.vertexAttributeKeys.Position),c.addVertexAttribute(i,b.vertexAttributeKeys.Color),c.addUniform(j),c.addUniform(k),c.addUniform(l),c.addUniform(m),c.addShader(g),c.addShader(f),a.addAttribute(c),a},b.utils.createPointGeometryMaterial=function(a){"use strict";a=void 0===a?1:a;var c=new b.material,d=new b.blend,e=new b.shaderProgram,f=b.utils.createPointVertexShader(b.GL),g=b.utils.createFragmentShader(b.GL),h=new b.vertexAttribute("vertexPosition"),i=new b.vertexAttribute("vertexColor"),j=new b.vertexAttribute("vertexSize"),k=new b.floatUniform("opacity",a),l=new b.modelViewUniform("modelViewMatrix"),m=new b.projectionUniform("projectionMatrix");return e.addVertexAttribute(h,b.vertexAttributeKeys.Position),e.addVertexAttribute(i,b.vertexAttributeKeys.Color),e.addVertexAttribute(j,b.vertexAttributeKeys.Scalar),e.addUniform(k),e.addUniform(l),e.addUniform(m),e.addShader(g),e.addShader(f),c.addAttribute(e),c.addAttribute(d),c},b.utils.createPhongMaterial=function(){"use strict";var a=new b.material,c=new b.shaderProgram,d=b.utils.createPhongVertexShader(b.GL),e=b.utils.createPhongFragmentShader(b.GL),f=new b.vertexAttribute("vertexPosition"),g=new b.vertexAttribute("vertexNormal"),h=new b.vertexAttribute("vertexColor"),i=new b.floatUniform("opacity",1),j=new b.modelViewUniform("modelViewMatrix"),k=new b.normalMatrixUniform("normalMatrix"),l=new b.projectionUniform("projectionMatrix");return c.addVertexAttribute(f,b.vertexAttributeKeys.Position),c.addVertexAttribute(g,b.vertexAttributeKeys.Normal),c.addVertexAttribute(h,b.vertexAttributeKeys.Color),c.addUniform(i),c.addUniform(j),c.addUniform(l),c.addUniform(k),c.addShader(e),c.addShader(d),a.addAttribute(c),a},b.utils.createColorMaterial=function(){"use strict";var a=new b.material,c=new b.blend,d=new b.shaderProgram,e=b.utils.createVertexShader(b.GL),f=b.utils.createFragmentShader(b.GL),g=new b.vertexAttribute("vertexPosition"),h=new b.vertexAttribute("textureCoord"),i=new b.vertexAttribute("vertexColor"),j=new b.floatUniform("pointSize",5),k=new b.floatUniform("opacity",1),l=new b.modelViewUniform("modelViewMatrix"),m=new b.projectionUniform("projectionMatrix");return d.addVertexAttribute(g,b.vertexAttributeKeys.Position),d.addVertexAttribute(i,b.vertexAttributeKeys.Color),d.addVertexAttribute(h,b.vertexAttributeKeys.TextureCoordinate),d.addUniform(j),d.addUniform(k),d.addUniform(l),d.addUniform(m),d.addShader(f),d.addShader(e),a.addAttribute(d),a.addAttribute(c),a},b.utils.createColorMappedMaterial=function(a){"use strict";a||(a=new b.lookupTable);var c=a.range(),d=new b.material,e=new b.blend,f=new b.shaderProgram,g=b.utils.createVertexShaderColorMap(b.GL,c[0],c[1]),h=b.utils.createFragmentShaderColorMap(b.GL),i=new b.vertexAttribute("vertexPosition"),j=new b.vertexAttribute("vertexScalar"),k=new b.floatUniform("pointSize",5),l=new b.floatUniform("opacity",1),m=new b.floatUniform("lutMin",c[0]),n=new b.floatUniform("lutMax",c[1]),o=new b.modelViewUniform("modelViewMatrix"),p=new b.projectionUniform("projectionMatrix"),q=new b.uniform(b.GL.FLOAT,"sampler2d"),r=a;return q.set(0),f.addVertexAttribute(i,b.vertexAttributeKeys.Position),f.addVertexAttribute(j,b.vertexAttributeKeys.Scalar),f.addUniform(k),f.addUniform(l),f.addUniform(m),f.addUniform(n),f.addUniform(o),f.addUniform(p),f.addShader(h),f.addShader(g),d.addAttribute(f),d.addAttribute(e),d.addAttribute(r),d},b.utils.updateColorMappedMaterial=function(a,b){"use strict";if(!a)return void console.log("[warning] Invalid material. Nothing to update.");if(!b)return void console.log("[warning] Invalid lookup table. Nothing to update.");var c=a.shaderProgram().uniform("lutMin"),d=a.shaderProgram().uniform("lutMax");c.set(b.range()[0]),d.set(b.range()[1]),a.setAttribute(b)},b.utils.createSolidColorMaterial=function(a){"use strict";a||(a=[1,1,1]);var c=new b.material,d=new b.blend,e=new b.shaderProgram,f=b.utils.createVertexShaderSolidColor(b.GL),g=b.utils.createFragmentShaderSolidColor(b.GL,a),h=new b.vertexAttribute("vertexPosition"),i=new b.floatUniform("pointSize",5),j=new b.floatUniform("opacity",1),k=new b.modelViewUniform("modelViewMatrix"),l=new b.projectionUniform("projectionMatrix");return e.addVertexAttribute(h,b.vertexAttributeKeys.Position),e.addUniform(i),e.addUniform(j),e.addUniform(k),e.addUniform(l),e.addShader(g),e.addShader(f),c.addAttribute(e),c.addAttribute(d),c},b.utils.createPointSpritesMaterial=function(a,c){"use strict";var d=void 0===c?[0,1]:c.range(),e=new b.material,f=new b.blend,g=new b.shaderProgram,h=b.utils.createPointSpritesVertexShader(b.GL),i=b.utils.createPointSpritesFragmentShader(b.GL),j=new b.vertexAttribute("vertexPosition"),k=new b.vertexAttribute("vertexColor"),l=new b.floatUniform("height",0),m=new b.floatUniform("vertexColorWeight",0),n=new b.floatUniform("lutMin",d[0]),o=new b.floatUniform("lutMax",d[1]),p=new b.modelViewUniform("modelViewMatrix"),q=new b.projectionUniform("projectionMatrix"),r=new b.uniform(b.GL.INT,"opacityLookup"),s=new b.uniform(b.GL.INT,"scalarsToColors"),t=new b.uniform(b.GL.INT,"useScalarsToColors"),u=new b.uniform(b.GL.INT,"useVertexColors"),v=new b.uniform(b.GL.FLOAT_VEC2,"pointSize"),w=new b.texture;return r.set(0),s.set(1),t.set(0),u.set(0),v.set([1,1]),g.addVertexAttribute(j,b.vertexAttributeKeys.Position),g.addVertexAttribute(k,b.vertexAttributeKeys.Color),g.addUniform(l),g.addUniform(m),g.addUniform(p),g.addUniform(q),g.addUniform(r),g.addUniform(u),g.addUniform(t),g.addUniform(v),g.addShader(i),g.addShader(h),e.addAttribute(g),e.addAttribute(f),c&&(g.addUniform(s),t.set(1),g.addUniform(n),g.addUniform(o),c.setTextureUnit(1),e.addAttribute(c)),w.setImage(a),w.setTextureUnit(0),e.addAttribute(w),e},b.utils.createPlane=function(a,c,d,e,f,g,h,i,j){"use strict";var k=new b.mapper,l=new b.planeSource,m=b.utils.createGeometryMaterial(),n=new b.actor;return l.setOrigin(a,c,d),l.setPoint1(e,f,g),l.setPoint2(h,i,j),k.setGeometryData(l.create()),n.setMapper(k),n.setMaterial(m),n},b.utils.createTexturePlane=function(a,c,d,e,f,g,h,i,j,k){"use strict";var l=new b.mapper,m=new b.planeSource,n=b.utils.createTextureMaterial(k,[a,c,d]),o=new b.actor;return m.setPoint1(e-a,f-c,g-d),m.setPoint2(h-a,i-c,j-d),l.setGeometryData(m.create()),o.setMapper(l),o.setMaterial(n),o},b.utils.createPoints=function(a,c,d,e,f){"use strict";if(!a)return console.log("[ERROR] Cannot create points without positions"),null;f=void 0===f?1:f;var g=new b.mapper,h=new b.pointSource,i=b.utils.createPointGeometryMaterial(f),j=new b.actor;return h.setPositions(a),d&&h.setColors(d),e&&h.setTextureCoordinates(e),c?h.setSize(c):h.setSize(1),g.setGeometryData(h.create()),j.setMapper(g),j.setMaterial(i),j},b.utils.createPointSprites=function(a,c,d,e){"use strict";if(!a)return console.log("[ERROR] Point sprites requires an image"),null;if(!c)return console.log("[ERROR] Cannot create points without positions"),null;var f=new b.mapper,g=new b.pointSource,h=b.utils.createPointSpritesMaterial(a),i=new b.actor;return g.setPositions(c),d&&g.setColors(d),e&&g.setTextureCoordinates(e),f.setGeometryData(g.create()),i.setMapper(f),i.setMaterial(h),i},b.utils.createLines=function(a,c){"use strict";if(!a)return console.log("[ERROR] Cannot create points without positions"),null;var d=new b.mapper,e=new b.lineSource,f=b.utils.createGeometryMaterial(),g=new b.actor;return e.setPositions(a),c&&e.setColors(c),d.setGeometryData(e.create()),g.setMapper(d),g.setMaterial(f),g},b.utils.createColorLegend=function(a,c,d,e,f,g,h){"use strict";function i(a,c,d){if(!c)return void console.log("[error] Create labels requires positions (x,y,z) array");if(c.length%3!==0)return void console.log("[error] Create labels require positions array contain 3d points");if(!d)return void console.log("[error] Create labels requires Valid range");var e,f=null,g=b.utils.computePowerOfTwo(48),h=0,i=[],j=[],k=[],l=[],m=c[6]-c[0],n=4;for(j.length=3,k.length=3,l.length=3,e=0;2>e;e+=1)h=e*(c.length-3),j[0]=c[h]-m,j[1]=c[h+1]-2*m,j[2]=c[h+2],k[0]=c[h]+m,k[1]=j[1],k[2]=j[2],l[0]=j[0],l[1]=c[1],l[2]=j[2],f=b.utils.createTexturePlane(j[0],j[1],j[2],k[0],k[1],k[2],l[0],l[1],l[2],!0), +f.setReferenceFrame(b.boundingObject.ReferenceFrame.Absolute),f.material().setBinNumber(b.material.RenderBin.Overlay),f.material().addAttribute(b.utils.create2DTexture(d[e].toFixed(2).toString(),12,null)),i.push(f);return j[0]=.5*(c[0]+c[c.length-3]-g),j[1]=c[1]+n,j[2]=c[2],k[0]=j[0]+g,k[1]=j[1],k[2]=j[2],l[0]=j[0],l[1]=j[1]+g,l[2]=j[2],f=b.utils.createTexturePlane(j[0],j[1],j[2],k[0],k[1],k[2],l[0],l[1],l[2],!0),f.setReferenceFrame(b.boundingObject.ReferenceFrame.Absolute),f.material().setBinNumber(b.material.RenderBin.Overlay),f.material().addAttribute(b.utils.create2DTexture(a,24,null)),i.push(f),i}function j(a,b,c,d,e,f,g,h,j,k,l,m,n,o,p){p=p;var q=j-f,r=null,s=q/m,t=[],u=[];for(r=0;m>=r;r+=1)t.push(f+s*r),t.push(g),t.push(h),t.push(f+s*r),t.push(g+o),t.push(h);return u=u.concat(i(a,t,b.range()))}if(!c)return console.log("[error] Invalid lookup table"),[];var k=d[0]+e,l=d[1],m=0,n=d[0],o=d[1]+f,p=0,q=[],r=null,s=null,t=b.groupNode();return r=b.utils.createTexturePlane(d[0],d[1],d[2],k,l,m,n,o,p,!0),s=r.material(),s.addAttribute(c),r.setMaterial(s),t.addChild(r),r.material().setBinNumber(b.material.RenderBin.Overlay),r.setReferenceFrame(b.boundingObject.ReferenceFrame.Absolute),q.push(r),q=q.concat(j(a,c,d[0],d[1],d[1],n,l,m,k,l,m,g,h,5,3))},b.utils.create2DTexture=function(a,c,d,e,f,g,h){"use strict";var i=document.getElementById("textRendering"),j=null,k=b.texture();return e=e||"sans-serif",f=f||"center",g=g||"bottom","undefined"==typeof h&&(h=!0),i||(i=document.createElement("canvas")),j=i.getContext("2d"),i.setAttribute("id","textRendering"),i.style.display="none",i.height=b.utils.computePowerOfTwo(8*c),i.width=i.height,j.fillStyle="rgba(0, 0, 0, 0)",j.fillRect(0,0,j.canvas.width,j.canvas.height),j.fillStyle="rgba(200, 85, 10, 1.0)",j.textAlign=f,j.textBaseline=g,j.font=4*c+"px "+e,h&&(j.font="bold "+j.font),j.fillText(a,i.width/2,i.height/2,i.width),k.setImage(i),k.updateDimensions(),k},b.picker=function(){"use strict";if(!(this instanceof b.picker))return new b.picker;b.object.call(this);var a=[];return this.getActors=function(){return a},this.pick=function(b,c,d){if(void 0===b)return 0;if(void 0===c)return 0;if(void 0===d)return 0;a=[];var e,f,g,h,i,j,k,l,m,n,o,p=d.camera(),q=d.width(),r=d.height(),s=p.focalPoint(),t=vec4.fromValues(s[0],s[1],s[2],1),u=d.worldToDisplay(t,p.viewMatrix(),p.projectionMatrix(),q,r),v=vec4.fromValues(b,c,u[2],1),w=d.displayToWorld(v,p.viewMatrix(),p.projectionMatrix(),q,r),x=p.position(),y=[];for(g=0;3>g;g+=1)y[g]=w[g]-x[g];for(e=d.sceneRoot().children(),f=0,g=0;g=0?(i=(h[0]-x[0])/y[0],j=(h[1]-x[0])/y[0]):(i=(h[1]-x[0])/y[0],j=(h[0]-x[0])/y[0]),y[1]>=0?(k=(h[2]-x[1])/y[1],l=(h[3]-x[1])/y[1]):(k=(h[3]-x[1])/y[1],l=(h[2]-x[1])/y[1]),i>l||k>j)continue;if(k>i&&(i=k),j>l&&(j=l),y[2]>=0?(m=(h[4]-x[2])/y[2],n=(h[5]-x[2])/y[2]):(m=(h[5]-x[2])/y[2],n=(h[4]-x[2])/y[2]),i>n||m>j)continue;m>i&&(i=m),j>n&&(j=n),a[f]=o,f+=1}return f},this},inherit(b.picker,b.object),b.shapefileReader=function(){"use strict";if(!(this instanceof b.shapefileReader))return new b.shapefileReader;var a=this,c=0,d=1,e=5,f=3;return this.int8=function(a,b){return a.charCodeAt(b)},this.bint32=function(a,b){return((255&a.charCodeAt(b))<<24)+((255&a.charCodeAt(b+1))<<16)+((255&a.charCodeAt(b+2))<<8)+(255&a.charCodeAt(b+3))},this.lint32=function(a,b){return((255&a.charCodeAt(b+3))<<24)+((255&a.charCodeAt(b+2))<<16)+((255&a.charCodeAt(b+1))<<8)+(255&a.charCodeAt(b))},this.bint16=function(a,b){return((255&a.charCodeAt(b))<<8)+(255&a.charCodeAt(b+1))},this.lint16=function(a,b){return((255&a.charCodeAt(b+1))<<8)+(255&a.charCodeAt(b))},this.ldbl64=function(a,b){var c=255&a.charCodeAt(b),d=255&a.charCodeAt(b+1),e=255&a.charCodeAt(b+2),f=255&a.charCodeAt(b+3),g=255&a.charCodeAt(b+4),h=255&a.charCodeAt(b+5),i=255&a.charCodeAt(b+6),j=255&a.charCodeAt(b+7),k=1-2*(j>>7),l=((127&j)<<4)+((240&i)>>4)-1023,m=(15&i)*Math.pow(2,48)+h*Math.pow(2,40)+g*Math.pow(2,32)+f*Math.pow(2,24)+e*Math.pow(2,16)+d*Math.pow(2,8)+c;return k*(1+m*Math.pow(2,-52))*Math.pow(2,l)},this.lfloat32=function(a,b){var c=255&a.charCodeAt(b),d=255&a.charCodeAt(b+1),e=255&a.charCodeAt(b+2),f=255&a.charCodeAt(b+3),g=1-2*(f>>7),h=((127&f)<<1)+((254&e)>>7)-127,i=(127&e)*Math.pow(2,16)+d*Math.pow(2,8)+c;return g*(1+i*Math.pow(2,-23))*Math.pow(2,h)},this.str=function(a,b,c){for(var d=[],e=b;b+c>e;){var f=a[e];if(0===f.charCodeAt(0))break;d.push(f),e+=1}return d.join("")},this.readHeader=function(a){var b=this.bint32(a,0),c=this.bint32(a,24),d=this.lint32(a,28),e=this.lint32(a,32);return{code:b,length:c,version:d,shapetype:e}},this.loadShx=function(b){for(var c=[],d=function(d){return c.push(2*a.bint32(b,d)),d+8},e=100;ej;)k.push(c(j)),j+=i;for(var l=[],m=f;f+e*g>m;){var n=a.str(b,m,1);if("*"===n)m+=g;else{m+=1;for(var o={},p=0;p=d;g-=1){var h=a.ldbl64(b,c+16*g),i=a.ldbl64(b,c+16*g+8);f.push([h,i])}return f},m=function(g){var h,i,j,m,n,o,p,q,r,s=g+8,t=a.lint32(b,s);if(t===c)console.log("NULL Shape");else if(t===d){var u=a.ldbl64(b,s+4),v=a.ldbl64(b,s+12);k.push({type:"Point",attr:{},geom:[[u,v]]})}else if(t===e){for(h=a.lint32(b,s+36),i=a.lint32(b,s+40),j=g+52,m=g+52+4*h,r=[],n=0;h>n;n+=1)o=a.lint32(b,j+4*n),p=h>n+1?a.lint32(b,j+4*(n+1)):i,q=l(m,o,p),r.push(q);k.push({type:"Polygon",attr:{},geom:[r]})}else{if(t!==f)throw"Not Implemented: "+t;for(h=a.lint32(b,s+36),i=a.lint32(b,s+40),j=g+52,m=g+52+4*h,r=[],n=0;h>n;n+=1)o=a.lint32(b,j+4*n),p=h>n+1?a.lint32(b,j+4*(n+1)):i,q=l(m,o,p),r.push(q);k.push({type:"Polyline",attr:{},geom:[r]})}},n=this.loadDBF(g);for(j=0;j=i.length)return h;if(a=i.charAt(j),j+=1,c[a])return c[a];if("A"===a)return 0}return h},this.decode64=function(a){var b="",c=new Array(4),d=!1;for(i=a,j=0;!d&&(c[0]=this.readReverseBase64())!==h&&(c[1]=this.readReverseBase64())!==h;)c[2]=this.readReverseBase64(),c[3]=this.readReverseBase64(),b+=this.ntos(c[0]<<2&255|c[1]>>4),c[2]!==h?(b+=this.ntos(c[1]<<4&255|c[2]>>2),c[3]!==h?b+=this.ntos(c[2]<<6&255|c[3]):d=!0):d=!0;return b},this.readNumber=function(a){var b=a[k++]+(a[k++]<<8)+(a[k++]<<16)+(a[k++]<<24);return b},this.readF3Array=function(a,b){var c,d=4*a*3,e=new Int8Array(d),f=null;for(c=0;d>c;c+=1)e[c]=b[k],k+=1;return f=new Float32Array(e.buffer)},this.readColorArray=function(a,b,c){var d,e=0,f=new Array(3*a);for(d=0;a>d;d+=1)f[e++]=b[k++]/255,f[e++]=b[k++]/255,f[e++]=b[k++]/255,k++;c.insert(f)},this.parseObject=function(a){var c,d,e,f,g,h,i,j,n,o,p,q=new b.geometryData,r=b.mapper(),s=[],t=null,u=null,v=null,w=null;for(u=atob(a.data),m=0;ml;l+=1)q[r++]=f[3*l],q[r++]=f[3*l+1],q[r++]=f[3*l+2];for(m.insert(q),a.addSource(m),n=new b.sourceDataC3fv,this.readColorArray(e,c,n),a.addSource(n),o=new b.lines,a.addPrimitive(o),d=this.readNumber(c),g=new Int8Array(2*d),l=0;2*d>l;l+=1)g[l]=c[k],k+=1;for(h=new Uint16Array(g.buffer),o.setIndices(h),o.setPrimitiveType(b.GL.LINES),i=64,g=new Int8Array(i),l=0;i>l;l+=1)g[l]=c[k],k+=1;return j=new Float32Array(g.buffer),mat4.copy(p,j),p},this.parseMeshData=function(a,c){var d,e,f,g,h,i,j,l,m=null,n=null,o=null,p=mat4.create(),q=null,r=null,s=0;for(e=this.readNumber(c),r=new Array(6*e),m=new b.sourceDataP3N3f,f=this.readF3Array(e,c),o=this.readF3Array(e,c),l=0;e>l;l+=1)r[s++]=f[3*l],r[s++]=f[3*l+1],r[s++]=f[3*l+2],r[s++]=o[3*l],r[s++]=o[3*l+1],r[s++]=o[3*l+2];for(m.insert(r),a.addSource(m),n=new b.sourceDataC3fv,this.readColorArray(e,c,n),a.addSource(n),g=[],q=new b.triangles,d=this.readNumber(c),g=new Int8Array(2*d),l=0;2*d>l;l+=1)g[l]=c[k],k+=1;for(h=new Uint16Array(g.buffer),q.setIndices(h),a.addPrimitive(q),i=64,g=new Int8Array(i),l=0;i>l;l+=1)g[l]=c[k],k+=1;return j=new Float32Array(g.buffer),mat4.copy(p,j),p},this.parsePointData=function(a,c){var d,e,f,g,h,i,j=mat4.create(),l=null,n=null,o=null,p=null,q=0;for(d=this.readNumber(c),p=new Array(3*d),l=new b.sourceDataP3fv,e=this.readF3Array(d,c),f=new Uint16Array(d),m=0;d>m;m+=1)f[m]=m,p[q++]=e[3*m],p[q++]=e[3*m+1],p[q++]=e[3*m+2];for(l.insert(p),a.addSource(l),n=new b.sourceDataC3fv,this.readColorArray(d,c,n),a.addSource(n),o=new b.points,o.setIndices(f),a.addPrimitive(o),h=64,g=new Int8Array(h),m=0;h>m;m+=1)g[m]=c[k],k+=1;return i=new Float32Array(g.buffer),mat4.copy(j,i),j},this.parseColorMapData=function(a,b,c){var d,e,f,g,h,i={};for(i.numOfColors=c,e=8,d=new Int8Array(e),g=0;e>g;g+=1)d[g]=b[k],k+=1;for(i.position=new Float32Array(d.buffer),e=8,d=new Int8Array(e),g=0;e>g;g+=1)d[g]=b[k],k+=1;for(i.size=new Float32Array(d.buffer),i.colors=[],h=0;hg;g+=1)d[g]=b[k],k+=1;f=[new Float32Array(d.buffer)[0],b[k++],b[k++],b[k++]],i.colors[h]=f}for(i.orientation=b[k++],i.numOfLabels=b[k++],i.title="";k=0;b-=1)a=this.getRenderer(b),this.parseSceneMetadata(a,b);return l},this.createViewer=function(a){var c;return null===l&&(g=a,l=b.viewer(a),l.init(),l.renderWindow().removeRenderer(l.renderWindow().activeRenderer()),l.renderWindow().addRenderer(new b.depthPeelRenderer),d[0]=l.renderWindow().activeRenderer(),l.renderWindow().resize(a.width,a.height),c=b.pvwInteractorStyle(),l.setInteractorStyle(c)),l},this.deleteViewer=function(){d={},l=null},this.updateCanvas=function(a){return g=a,l.renderWindow().resize(a.width,a.height),l},this.numObjects=function(){return e},this.getRenderer=function(a){var c;return c=d[a],(null===c||"undefined"==typeof c)&&(c=new b.renderer,c.setResetScene(!1),c.setResetClippingRange(!1),l.renderWindow().addRenderer(c),0!==a&&c.camera().setClearMask(b.GL.DepthBufferBit),d[a]=c),c},this.setVtkScene=function(a){f=a},this},b.DataBuffers=function(a){"use strict";if(!(this instanceof b.DataBuffers))return new b.DataBuffers(a);var c,d={};c=a||0===a?a:256;var e=0,f=function(a,b,c,d){if(!a)throw"No destination";c||(c=0),d||(d=b.length);for(var e=0;d>e;e+=1)a[c+e]=b[e]},g=function(a){var b=c;for(a>2*b&&(b=a);a>b;)b*=2;c=b;for(var e in d)if(d.hasOwnProperty(e)){var g=new Float32Array(b*d[e].len),h=d[e].array;f(g,h),d[e].array=g,d[e].dirty=!0}};this.create=function(a,b){if(!b||0>b)throw"Length of buffer must be a positive integer";var e=new Float32Array(c*b);return d[a]={array:e,len:b,dirty:!1},d[a].array},this.alloc=function(a){e+a>=c&&g(e+a);var b=e;return e+=a,b},this.get=function(a){return d[a].array},this.write=function(a,b,e,g){if(e+g>c)throw"Write would exceed buffer size";f(d[a].array,b,e*d[a].len,g*d[a].len),d[a].dirty=!0},this.repeat=function(a,b,e,g){if(e+g>c)throw"Repeat would exceed buffer size";for(var h=0;g>h;h+=1)f(d[a].array,b,(e+h)*d[a].len,d[a].len);d[a].dirty=!0},this.count=function(){return e},this.data=function(a){return d[a].array}},b}); //# sourceMappingURL=vgl.min.js.map \ No newline at end of file