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(function() {
 21  
 22 /**************************************************************************************************************/
 23 
 24 /** 
 25 	@constructor TileIndexBuffer
 26 	TileIndexBuffer
 27  */
 28 var TileIndexBuffer = function( renderContext, config )
 29 {
 30 	this.renderContext = renderContext;
 31 	this.config = config;
 32 	this.solidIndexBuffer = null;
 33 	this.subSolidIndexBuffer = [ null, null, null, null ];
 34 	this.subIndices = [ null, null, null, null ];
 35 }
 36 
 37 /**************************************************************************************************************/
 38 
 39 /**  
 40  * Reset the index buffers.
 41  */
 42 TileIndexBuffer.prototype.reset = function()
 43 {	
 44 	var gl = this.renderContext.gl;
 45 	for ( var i=0; i < 4; i++ )
 46 	{
 47 		if ( this.subSolidIndexBuffer[i] )
 48 		{
 49 			gl.deleteBuffer( this.subSolidIndexBuffer[i] );
 50 			this.subSolidIndexBuffer[i] = null;
 51 		}
 52 	}
 53 	if ( this.solidIndexBuffer )
 54 	{
 55 		gl.deleteBuffer( this.solidIndexBuffer );
 56 		this.solidIndexBuffer = null;
 57 	}
 58 }
 59 
 60 /**************************************************************************************************************/
 61 
 62 /**
 63  *	Get index buffer for sub solid
 64  */
 65 TileIndexBuffer.prototype.getSubSolid = function(ii)
 66 {
 67 	if ( this.subSolidIndexBuffer[ii] == null )
 68 	{
 69 		var i = ii % 2;
 70 		var j = Math.floor( ii / 2 );
 71 		
 72 		var size = this.config.tesselation;
 73 		var halfTesselation = (size-1) / 2;
 74 		
 75 		// Build the sub grid for 'inside' tile
 76 		var indices = [];
 77 		for ( var n=halfTesselation*j; n < halfTesselation*(j+1); n++)
 78 		{
 79 			for ( var k=halfTesselation*i; k < halfTesselation*(i+1); k++)
 80 			{
 81 				indices.push( n * size + k );
 82 				indices.push( (n+1) * size + k );
 83 				indices.push( n * size + k + 1 );
 84 				
 85 				indices.push( n * size + k + 1 );
 86 				indices.push( (n+1) * size + k );
 87 				indices.push( (n+1) * size + k + 1 );
 88 			}
 89 		}
 90 		
 91 		this.subIndices[ii] = indices;
 92 
 93 		if (this.config.skirt)
 94 		{
 95 			// Build skirts
 96 			// Top skirt
 97 			var start = (j == 0) ? size * size : size * size + 4 * size;
 98 			var src = (j == 0) ? 0 : halfTesselation * size;
 99 			for ( var n = halfTesselation*i; n < halfTesselation*(i+1); n++)
100 			{
101 				indices.push( start + n );
102 				indices.push( src + n );
103 				indices.push( start + n + 1 );
104 				
105 				indices.push( start + n + 1 );
106 				indices.push( src + n );
107 				indices.push( src + n + 1 );
108 			}
109 		
110 			// Bottom skirt
111 			start = (j == 0) ? size * size + 4 * size : size * size + size;
112 			src = (j == 0) ? halfTesselation * size : (size-1) * size;
113 			for ( var n = halfTesselation*i; n < halfTesselation*(i+1); n++)
114 			{
115 				indices.push( src + n );
116 				indices.push( start + n );
117 				indices.push( src + n + 1 );
118 				
119 				indices.push( src + n + 1 );
120 				indices.push( start + n );
121 				indices.push( start + n + 1 );
122 			}
123 				
124 			// Left skirt
125 			start = (i == 0) ? size * size + 2 * size : size * size + 5 * size;
126 			src = (i == 0) ? 0 : halfTesselation;
127 			for ( var k=halfTesselation*j; k < halfTesselation*(j+1); k++)
128 			{
129 				indices.push( start + k );
130 				indices.push( start + k + 1 );
131 				indices.push( src + k * size );
132 				
133 				indices.push( src + k * size );
134 				indices.push( start + k + 1);
135 				indices.push( src + (k+1) * size );
136 			}
137 			
138 			// Right skirt
139 			start = (i == 0) ? size * size + 5 * size : size * size + 3 * size;
140 			src = (i == 0) ? halfTesselation : size - 1;
141 			for ( var k=halfTesselation*j; k < halfTesselation*(j+1); k++)
142 			{
143 				indices.push( k * size + src );
144 				indices.push( (k+1) * size + src );
145 				indices.push( start + k );
146 				
147 				indices.push( start + k );
148 				indices.push( (k+1) * size + src );
149 				indices.push( start + k + 1 );
150 			}
151 		}
152 		
153 		var gl = this.renderContext.gl;
154 		var ib = gl.createBuffer();
155 		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib);
156 		gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
157 		ib.numIndices = indices.length;
158 		this.subSolidIndexBuffer[ii] = ib;
159 	}
160 	
161 	return this.subSolidIndexBuffer[ii];
162 }
163 
164 /**************************************************************************************************************/
165 
166 /*
167 	Build index buffer
168  */
169 TileIndexBuffer.prototype.getSolid = function()
170 {
171 	if ( this.solidIndexBuffer == null )
172 	{
173 		var size = this.config.tesselation;
174 		var indices = [];
175 		// Build the grid
176 		for ( var j=0; j < size-1; j++)
177 		{
178 			for ( var i=0; i < size-1; i++)
179 			{
180 				indices.push( j * size + i );
181 				indices.push( (j+1) * size + i );
182 				indices.push( j * size + i + 1 );
183 				
184 				indices.push( j * size + i + 1 );
185 				indices.push( (j+1) * size + i );
186 				indices.push( (j+1) * size + i + 1 );
187 			}
188 		}
189 		
190 		if (this.config.skirt)
191 		{
192 			// Top skirt
193 			var start = size * size;
194 			for ( var i = 0; i < size-1; i++)
195 			{
196 				indices.push( start + i );
197 				indices.push( i );
198 				indices.push( start + i + 1 );
199 				
200 				indices.push( start + i + 1 );
201 				indices.push( i );
202 				indices.push( i + 1 );
203 			}
204 			
205 			// Bottom skirt
206 			start += size;
207 			for ( var i=0; i < size-1; i++)
208 			{
209 				indices.push( (size-1) * size + i );
210 				indices.push( start + i );
211 				indices.push( (size-1) * size + i + 1 );
212 				
213 				indices.push( (size-1) * size + i + 1 );
214 				indices.push( start + i );
215 				indices.push( start + i + 1 );
216 			}
217 				
218 			// Left skirt
219 			start += size;
220 			for ( var j=0; j < size-1; j++)
221 			{
222 				indices.push( start + j );
223 				indices.push( start + j + 1 );
224 				indices.push( j * size );
225 				
226 				indices.push( j * size );
227 				indices.push( start + j + 1);
228 				indices.push( (j+1) * size );
229 			}
230 
231 			// Right skirt
232 			start += size;
233 			for ( var j=0; j < size-1; j++)
234 			{
235 				indices.push( j * size + size - 1 );
236 				indices.push( (j+1) * size + size - 1 );
237 				indices.push( start + j );
238 				
239 				indices.push( start + j );
240 				indices.push( (j+1) * size + size - 1 );
241 				indices.push( start + j + 1 );
242 			}
243 		}
244 		
245 		var gl = this.renderContext.gl;
246 		var ib = gl.createBuffer();
247 		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib);
248 		gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
249 		this.numIndices = indices.length;
250 		
251 		this.solidIndexBuffer = ib;
252 		this.solidIndexBuffer.numIndices = indices.length;
253 	}
254 	
255 	return this.solidIndexBuffer;
256 }
257 
258 /**************************************************************************************************************/
259 
260 return TileIndexBuffer;
261 
262 });
263