1 /*************************************** 2 * Copyright 2011, 2012 GlobWeb contributors. 3 * 4 * This file is part of GlobWeb. 5 * 6 * GlobWeb is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * GlobWeb is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GlobWeb. If not, see <http://www.gnu.org/licenses/>. 18 ***************************************/ 19 20 define(['./Utils', './BaseLayer','./Program','./Tile'], 21 function(Utils, BaseLayer, Program, Tile) { 22 23 /**************************************************************************************************************/ 24 25 /** 26 @constructor 27 Function constructor for TileWireframeLayer 28 */ 29 var TileWireframeLayer = function( options ) 30 { 31 BaseLayer.prototype.constructor.call( this, options ); 32 this.outline = (options && options['outline']) ? options['outline'] : false; 33 this.globe = null; 34 this.program = null; 35 this.indexBuffer = null; 36 this.subIndexBuffer = [ null, null, null, null ]; 37 } 38 39 /**************************************************************************************************************/ 40 41 Utils.inherits( BaseLayer,TileWireframeLayer ); 42 43 /**************************************************************************************************************/ 44 45 /** 46 Build the index buffer 47 */ 48 TileWireframeLayer.prototype.buildIndexBuffer = function() 49 { 50 var gl = this.globe.renderContext.gl; 51 var size = this.globe.tileManager.tileConfig.tesselation; 52 var indices = []; 53 54 var step = this.outline ? size-1 : 1; 55 56 // Build horizontal lines 57 for ( var j=0; j < size; j += step) 58 { 59 for ( var i=0; i < size-1; i++) 60 { 61 indices.push( j * size + i ); 62 indices.push( j * size + i + 1 ); 63 } 64 } 65 66 // Build vertical lines 67 for ( var j=0; j < size; j += step) 68 { 69 for ( var i=0; i < size-1; i++) 70 { 71 indices.push( i * size + j ); 72 indices.push( (i+1) * size + j ); 73 } 74 } 75 76 77 var ib = gl.createBuffer(); 78 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib); 79 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); 80 81 ib.numIndices = indices.length; 82 this.indexBuffer = ib; 83 84 var halfTesselation = (size-1) / 2; 85 step = this.outline ? halfTesselation : 1; 86 for ( var ii = 0; ii < 4; ii++ ) 87 { 88 var i = ii % 2; 89 var j = Math.floor( ii / 2 ); 90 91 // Build the sub grid for 'inside' tile 92 var indices = []; 93 for ( var n=halfTesselation*j; n < halfTesselation*(j+1)+1; n+= step) 94 { 95 for ( var k=halfTesselation*i; k < halfTesselation*(i+1); k++) 96 { 97 indices.push( n * size + k ); 98 indices.push( n * size + k + 1 ); 99 } 100 } 101 for ( var n=halfTesselation*i; n < halfTesselation*(i+1)+1; n+= step) 102 { 103 for ( var k=halfTesselation*j; k < halfTesselation*(j+1); k++) 104 { 105 indices.push( k * size + n ); 106 indices.push( (k+1) * size + n ); 107 } 108 } 109 110 var ib = gl.createBuffer(); 111 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib); 112 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); 113 ib.numIndices = indices.length; 114 this.subIndexBuffer[ii] = ib; 115 } 116 } 117 118 /**************************************************************************************************************/ 119 120 /** 121 Attach the layer to the globe 122 */ 123 TileWireframeLayer.prototype._attach = function( g ) 124 { 125 BaseLayer.prototype._attach.call( this, g ); 126 127 if ( this._visible ) 128 { 129 this.globe.tileManager.addPostRenderer(this); 130 } 131 132 if (!this.program) 133 { 134 var vertexShader = "\ 135 attribute vec3 vertex;\n\ 136 uniform mat4 modelViewMatrix;\n\ 137 uniform mat4 projectionMatrix;\n\ 138 void main(void) \n\ 139 {\n\ 140 gl_Position = projectionMatrix * modelViewMatrix * vec4(vertex, 1.0);\n\ 141 }\n\ 142 "; 143 144 var fragmentShader = "\ 145 precision highp float; \n\ 146 uniform float alpha; \n\ 147 void main(void)\n\ 148 {\n\ 149 gl_FragColor = vec4(1.0,1.0,1.0,alpha);\n\ 150 }\n\ 151 "; 152 153 this.program = new Program(this.globe.renderContext); 154 this.program.createFromSource( vertexShader, fragmentShader ); 155 156 this.buildIndexBuffer(); 157 } 158 } 159 160 /**************************************************************************************************************/ 161 162 /** 163 Detach the layer from the globe 164 */ 165 TileWireframeLayer.prototype._detach = function() 166 { 167 this.globe.tileManager.removePostRenderer(this); 168 BaseLayer.prototype._detach.call(this); 169 } 170 171 /**************************************************************************************************************/ 172 173 /** 174 Render the tiles outline 175 */ 176 TileWireframeLayer.prototype.render = function( tiles ) 177 { 178 var rc = this.globe.renderContext; 179 var gl = rc.gl; 180 181 gl.enable(gl.BLEND); 182 183 // Setup program 184 this.program.apply(); 185 gl.uniformMatrix4fv(this.program.uniforms["projectionMatrix"], false, rc.projectionMatrix); 186 187 var vertexAttribute = this.program.attributes['vertex']; 188 var currentIB = null; 189 190 for ( var i = 0; i < tiles.length; i++ ) 191 { 192 var tile = tiles[i]; 193 194 var isLoaded = ( tile.state == Tile.State.LOADED ); 195 var isLevelZero = ( tile.parentIndex == -1 ); 196 197 // Update uniforms for modelview matrix 198 mat4.multiply( rc.viewMatrix, tile.matrix, rc.modelViewMatrix ); 199 gl.uniformMatrix4fv(this.program.uniforms["modelViewMatrix"], false, rc.modelViewMatrix); 200 gl.uniform1f(this.program.uniforms["alpha"], this.opacity() ); 201 202 // Bind the vertex buffer 203 gl.bindBuffer(gl.ARRAY_BUFFER, tile.vertexBuffer); 204 gl.vertexAttribPointer(vertexAttribute, 3, gl.FLOAT, false, 4*tile.config.vertexSize, 0); 205 206 var indexBuffer = ( isLoaded || isLevelZero ) ? this.indexBuffer : this.subIndexBuffer[tile.parentIndex]; 207 // Bind the index buffer only if different (index buffer is shared between tiles) 208 if ( currentIB != indexBuffer ) 209 { 210 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 211 currentIB = indexBuffer; 212 } 213 214 // Draw the tiles in wireframe mode 215 var numIndices = currentIB.numIndices; 216 gl.drawElements(gl.LINES, currentIB.numIndices, gl.UNSIGNED_SHORT, 0); 217 } 218 219 gl.disable(gl.BLEND); 220 } 221 222 /**************************************************************************************************************/ 223 224 /** 225 * Set visibility of the layer 226 */ 227 TileWireframeLayer.prototype.visible = function( arg ) 228 { 229 if ( typeof arg == "boolean" && this._visible != arg ) 230 { 231 this._visible = arg; 232 233 if ( arg ){ 234 this.globe.tileManager.addPostRenderer(this); 235 } 236 else 237 { 238 this.globe.tileManager.removePostRenderer(this); 239 } 240 } 241 242 return this._visible; 243 } 244 245 return TileWireframeLayer; 246 247 }); 248