1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies Inc.
  5  Copyright (c) 2009      On-Core
  6 
  7  http://www.cocos2d-x.org
  8 
  9  Permission is hereby granted, free of charge, to any person obtaining a copy
 10  of this software and associated documentation files (the "Software"), to deal
 11  in the Software without restriction, including without limitation the rights
 12  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 13  copies of the Software, and to permit persons to whom the Software is
 14  furnished to do so, subject to the following conditions:
 15 
 16  The above copyright notice and this permission notice shall be included in
 17  all copies or substantial portions of the Software.
 18 
 19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 25  THE SOFTWARE.
 26  ****************************************************************************/
 27 
 28 /**
 29  * Base class for cc.Grid
 30  * @class
 31  * @extends cc.Class
 32  */
 33 cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
 34     _active:false,
 35     _reuseGrid:0,
 36     _gridSize:null,
 37     _texture:null,
 38     _step:null,
 39     _grabber:null,
 40     _isTextureFlipped:false,
 41     _shaderProgram:null,
 42     _directorProjection:0,
 43 
 44     _dirty:false,
 45 
 46     /**
 47      * create one cc.GridBase Object
 48      * Constructor of cc.GridBase
 49      * @param {cc.Size} gridSize
 50      * @param {cc.Texture2D} [texture=]
 51      * @param {Boolean} [flipped=]
 52      */
 53     ctor:function (gridSize, texture, flipped) {
 54         cc._checkWebGLRenderMode();
 55         this._active=false;
 56         this._reuseGrid=0;
 57         this._gridSize=null;
 58         this._texture=null;
 59         this._step = cc.p(0, 0);
 60         this._grabber=null;
 61         this._isTextureFlipped=false;
 62         this._shaderProgram=null;
 63         this._directorProjection=0;
 64         this._dirty=false;
 65 
 66         if(gridSize !== undefined)
 67             this.initWithSize(gridSize, texture, flipped);
 68     },
 69 
 70     /**
 71      * whether or not the grid is active
 72      * @return {Boolean}
 73      */
 74     isActive:function () {
 75         return this._active;
 76     },
 77 
 78     /**
 79      * whether or not the grid is active
 80      * @param {Number} active
 81      */
 82     setActive:function (active) {
 83         this._active = active;
 84         if (!active) {
 85             var director = cc.director;
 86             var proj = director.getProjection();
 87             director.setProjection(proj);
 88         }
 89     },
 90 
 91     /**
 92      * get number of times that the grid will be reused
 93      * @return {Number}
 94      */
 95     getReuseGrid:function () {
 96         return this._reuseGrid;
 97     },
 98     /**
 99      * set number of times that the grid will be reused
100      * @param reuseGrid
101      */
102     setReuseGrid:function (reuseGrid) {
103         this._reuseGrid = reuseGrid;
104     },
105 
106     /**
107      * get size of the grid
108      * @return {cc.Size}
109      */
110     getGridSize:function () {
111         return cc.size(this._gridSize.width, this._gridSize.height);
112     },
113 
114     /**
115      * set size of the grid
116      * @param {cc.Size} gridSize
117      */
118     setGridSize:function (gridSize) {
119         this._gridSize.width = parseInt(gridSize.width);
120         this._gridSize.height = parseInt(gridSize.height);
121     },
122 
123     /**
124      * get pixels between the grids
125      * @return {cc.Point}
126      */
127     getStep:function () {
128         return cc.p(this._step.x, this._step.y);
129     },
130 
131     /**
132      * set pixels between the grids
133      * @param {cc.Point} step
134      */
135     setStep:function (step) {
136         this._step.x = step.x;
137         this._step.y = step.y;
138     },
139 
140     /**
141      * get wheter or not the texture is flipped
142      * @return {Boolean}
143      */
144     isTextureFlipped:function () {
145         return this._isTextureFlipped;
146     },
147 
148     /**
149      * set wheter or not the texture is flipped
150      * @param {Boolean} flipped
151      */
152     setTextureFlipped:function (flipped) {
153         if (this._isTextureFlipped != flipped) {
154             this._isTextureFlipped = flipped;
155             this.calculateVertexPoints();
156         }
157     },
158 
159     /**
160      *
161      * @param {cc.Size} gridSize
162      * @param {cc.Texture2D} [texture=]
163      * @param {Boolean} [flipped=false]
164      * @returns {boolean}
165      */
166     initWithSize:function (gridSize, texture, flipped) {
167         if (!texture) {
168             var director = cc.director;
169             var winSize = director.getWinSizeInPixels();
170 
171             var POTWide = cc.NextPOT(winSize.width);
172             var POTHigh = cc.NextPOT(winSize.height);
173 
174             var data = new Uint8Array(POTWide * POTHigh * 4);
175             if (!data) {
176                 cc.log("cocos2d: CCGrid: not enough memory.");
177                 return false;
178             }
179 
180             texture = new cc.Texture2D();
181             // we only use rgba8888
182             texture.initWithData(data, cc.Texture2D.PIXEL_FORMAT_RGBA8888, POTWide, POTHigh, winSize);
183             if (!texture) {
184                 cc.log("cocos2d: CCGrid: error creating texture");
185                 return false;
186             }
187         }
188 
189         flipped = flipped || false;
190 
191         this._active = false;
192         this._reuseGrid = 0;
193         this._gridSize = gridSize;
194         this._texture = texture;
195         this._isTextureFlipped = flipped;
196 
197         this._step.x = this._texture.width / gridSize.width;
198         this._step.y = this._texture.height / gridSize.height;
199 
200         this._grabber = new cc.Grabber();
201         if (!this._grabber)
202             return false;
203         this._grabber.grab(this._texture);
204         this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
205         this.calculateVertexPoints();
206         return true;
207     },
208 
209     beforeDraw:function () {
210         // save projection
211         this._directorProjection = cc.director.getProjection();
212 
213         // 2d projection
214         //    [director setProjection:kCCDirectorProjection2D];
215         this.set2DProjection();
216         this._grabber.beforeRender(this._texture);
217     },
218 
219     afterDraw:function (target) {
220         this._grabber.afterRender(this._texture);
221 
222         // restore projection
223         cc.director.setProjection(this._directorProjection);
224 
225         if (target.getCamera().isDirty()) {
226             var offset = target.getAnchorPointInPoints();
227 
228             //
229             // XXX: Camera should be applied in the AnchorPoint
230             //
231             cc.kmGLTranslatef(offset.x, offset.y, 0);
232             target.getCamera().locate();
233             cc.kmGLTranslatef(-offset.x, -offset.y, 0);
234         }
235 
236         cc.glBindTexture2D(this._texture);
237 
238         // restore projection for default FBO .fixed bug #543 #544
239         //TODO:         CCDirector::sharedDirector().setProjection(CCDirector::sharedDirector().getProjection());
240         //TODO:         CCDirector::sharedDirector().applyOrientation();
241         this.blit();
242     },
243 
244     blit:function () {
245         cc.log("cc.GridBase.blit(): Shall be overridden in subclass.");
246     },
247 
248     reuse:function () {
249         cc.log("cc.GridBase.reuse(): Shall be overridden in subclass.");
250     },
251 
252     calculateVertexPoints:function () {
253         cc.log("cc.GridBase.calculateVertexPoints(): Shall be overridden in subclass.");
254     },
255 
256     set2DProjection:function () {
257         var winSize = cc.director.getWinSizeInPixels();
258 
259         var gl = cc._renderContext;
260         gl.viewport(0, 0, winSize.width , winSize.height);
261         cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
262         cc.kmGLLoadIdentity();
263 
264         var orthoMatrix = new cc.kmMat4();
265         cc.kmMat4OrthographicProjection(orthoMatrix, 0, winSize.width, 0, winSize.height, -1, 1);
266         cc.kmGLMultMatrix(orthoMatrix);
267 
268         cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
269         cc.kmGLLoadIdentity();
270         cc.setProjectionMatrixDirty()
271     }
272 });
273 
274 /**
275  * create one cc.GridBase Object
276  * @deprecated
277  * @param {cc.Size} gridSize
278  * @param {cc.Texture2D} [texture=]
279  * @param {Boolean} [flipped=]
280  * @return {cc.GridBase}
281  */
282 cc.GridBase.create = function (gridSize, texture, flipped) {
283     return new cc.GridBase(gridSize, texture, flipped);
284 };
285 
286 /**
287  * cc.Grid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z
288  * @class
289  * @extends cc.GridBase
290  */
291 cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
292     _texCoordinates:null,
293     _vertices:null,
294     _originalVertices:null,
295     _indices:null,
296 
297     _texCoordinateBuffer:null,
298     _verticesBuffer:null,
299     _indicesBuffer:null,
300 
301     /**
302      * create one Grid3D object
303      * Constructor of cc.Grid3D
304      * @param {cc.Size} gridSize
305      * @param {cc.Texture2D} [texture=]
306      * @param {Boolean} [flipped=]
307      */
308     ctor:function (gridSize, texture, flipped) {
309         cc.GridBase.prototype.ctor.call(this);
310         this._texCoordinates=null;
311         this._vertices=null;
312         this._originalVertices=null;
313         this._indices=null;
314 
315         this._texCoordinateBuffer=null;
316         this._verticesBuffer=null;
317         this._indicesBuffer=null;
318 
319         if(gridSize !== undefined)
320             this.initWithSize(gridSize, texture, flipped);
321     },
322 
323     /**
324      * returns the vertex at a given position
325      * @param {cc.Point} pos
326      * @return {cc.Vertex3F}
327      */
328     vertex:function (pos) {
329         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
330             cc.log("cc.Grid3D.vertex() : Numbers must be integers");
331         var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
332         var locVertices = this._vertices;
333         return new cc.Vertex3F(locVertices[index], locVertices[index + 1], locVertices[index + 2]);
334     },
335 
336     /**
337      * returns the original (non-transformed) vertex at a given position
338      * @param {cc.Point} pos
339      * @return {cc.Vertex3F}
340      */
341     originalVertex:function (pos) {
342         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
343             cc.log("cc.Grid3D.originalVertex() : Numbers must be integers");
344         var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
345         var locOriginalVertices = this._originalVertices;
346         return new cc.Vertex3F(locOriginalVertices[index], locOriginalVertices[index + 1], locOriginalVertices[index + 2]);
347     },
348 
349     /**
350      * sets a new vertex at a given position
351      * @param {cc.Point} pos
352      * @param {cc.Vertex3F} vertex
353      */
354     setVertex:function (pos, vertex) {
355         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
356             cc.log("cc.Grid3D.setVertex() : Numbers must be integers");
357         var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
358         var vertArray = this._vertices;
359         vertArray[index] = vertex.x;
360         vertArray[index + 1] = vertex.y;
361         vertArray[index + 2] = vertex.z;
362         this._dirty = true;
363     },
364 
365     blit:function () {
366         var n = this._gridSize.width * this._gridSize.height;
367         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS);
368         this._shaderProgram.use();
369         this._shaderProgram.setUniformsForBuiltins();
370 
371         var gl = cc._renderContext, locDirty = this._dirty;
372         //
373         // Attributes
374         //
375         // position
376         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
377         if (locDirty)
378             gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
379         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 0, 0);
380 
381         // texCoords
382         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
383         if (locDirty)
384             gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
385         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, 0);
386 
387         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
388         if (locDirty)
389             gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
390         gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
391         if (locDirty)
392             this._dirty = false;
393         cc.incrementGLDraws(1);
394     },
395 
396     reuse:function () {
397         if (this._reuseGrid > 0) {
398             var locOriginalVertices = this._originalVertices, locVertices = this._vertices;
399             for (var i = 0, len =  this._vertices.length; i < len; i++)
400                 locOriginalVertices[i] = locVertices[i];
401             --this._reuseGrid;
402         }
403     },
404 
405     calculateVertexPoints:function () {
406         var gl = cc._renderContext;
407 
408         var width = this._texture.pixelsWidth;
409         var height = this._texture.pixelsHeight;
410         var imageH = this._texture.getContentSizeInPixels().height;
411         var locGridSize = this._gridSize;
412 
413         var numOfPoints = (locGridSize.width + 1) * (locGridSize.height + 1);
414         this._vertices = new Float32Array(numOfPoints * 3);
415         this._texCoordinates = new Float32Array(numOfPoints * 2);
416         this._indices = new Uint16Array(locGridSize.width * locGridSize.height * 6);
417 
418         if(this._verticesBuffer)
419             gl.deleteBuffer(this._verticesBuffer);
420         this._verticesBuffer = gl.createBuffer();
421         if(this._texCoordinateBuffer)
422             gl.deleteBuffer(this._texCoordinateBuffer);
423         this._texCoordinateBuffer = gl.createBuffer();
424         if(this._indicesBuffer)
425             gl.deleteBuffer(this._indicesBuffer);
426         this._indicesBuffer = gl.createBuffer();
427 
428         var x, y, i, locIndices = this._indices, locTexCoordinates = this._texCoordinates;
429         var locIsTextureFlipped = this._isTextureFlipped, locVertices = this._vertices;
430         for (x = 0; x < locGridSize.width; ++x) {
431             for (y = 0; y < locGridSize.height; ++y) {
432                 var idx = (y * locGridSize.width) + x;
433                 var x1 = x * this._step.x;
434                 var x2 = x1 + this._step.x;
435                 var y1 = y * this._step.y;
436                 var y2 = y1 + this._step.y;
437 
438                 var a = (x * (locGridSize.height + 1) + y);
439                 var b = ((x + 1) * (locGridSize.height + 1) + y);
440                 var c = ((x + 1) * (locGridSize.height + 1) + (y + 1));
441                 var d = (x * (locGridSize.height + 1) + (y + 1));
442 
443                 locIndices[idx * 6] = a;
444                 locIndices[idx * 6 + 1] = b;
445                 locIndices[idx * 6 + 2] = d;
446                 locIndices[idx * 6 + 3] = b;
447                 locIndices[idx * 6 + 4] = c;
448                 locIndices[idx * 6 + 5] = d;
449 
450                 var l1 = [a * 3, b * 3, c * 3, d * 3];
451                 var e = {x:x1, y:y1, z:0};   //new cc.Vertex3F(x1, y1, 0);
452                 var f = {x:x2, y:y1, z:0};   //new cc.Vertex3F(x2, y1, 0);
453                 var g = {x:x2, y:y2, z:0};   // new cc.Vertex3F(x2, y2, 0);
454                 var h = {x:x1, y:y2, z:0};   //new cc.Vertex3F(x1, y2, 0);
455 
456                 var l2 = [e, f, g, h];
457                 var tex1 = [a * 2, b * 2, c * 2, d * 2];
458                 var tex2 = [cc.p(x1, y1), cc.p(x2, y1), cc.p(x2, y2), cc.p(x1, y2)];
459                 for (i = 0; i < 4; ++i) {
460                     locVertices[l1[i]] = l2[i].x;
461                     locVertices[l1[i] + 1] = l2[i].y;
462                     locVertices[l1[i] + 2] = l2[i].z;
463                     locTexCoordinates[tex1[i]] = tex2[i].x / width;
464                     if (locIsTextureFlipped)
465                         locTexCoordinates[tex1[i] + 1] = (imageH - tex2[i].y) / height;
466                     else
467                         locTexCoordinates[tex1[i] + 1] = tex2[i].y / height;
468                 }
469             }
470         }
471         this._originalVertices = new Float32Array(this._vertices);
472 
473         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
474         gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
475         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
476         gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
477         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
478         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
479         this._dirty = true;
480     }
481 });
482 
483 /**
484  * create one Grid3D object
485  * @deprecated
486  * @param {cc.Size} gridSize
487  * @param {cc.Texture2D} [texture=]
488  * @param {Boolean} [flipped=]
489  * @return {cc.Grid3D}
490  */
491 cc.Grid3D.create = function (gridSize, texture, flipped) {
492     return new cc.Grid3D(gridSize, texture, flipped);
493 };
494 
495 /**
496  * cc.TiledGrid3D is a 3D grid implementation. It differs from Grid3D in that   <br/>
497  * the tiles can be separated from the grid.
498  * @class
499  * @extends cc.GridBase
500  */
501 cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
502     _texCoordinates:null,
503     _vertices:null,
504     _originalVertices:null,
505     _indices:null,
506 
507     _texCoordinateBuffer:null,
508     _verticesBuffer:null,
509     _indicesBuffer:null,
510 
511     /**
512      * create one TiledGrid3D object
513      * Constructor of cc.TiledGrid3D
514      * @param {cc.Size} gridSize
515      * @param {cc.Texture2D} [texture=]
516      * @param {Boolean} [flipped=]
517      */
518     ctor:function (gridSize, texture, flipped) {
519         cc.GridBase.prototype.ctor.call(this);
520         this._texCoordinates=null;
521         this._vertices=null;
522         this._originalVertices=null;
523         this._indices=null;
524 
525         this._texCoordinateBuffer=null;
526         this._verticesBuffer=null;
527         this._indicesBuffer=null;
528 
529         if(gridSize !== undefined)
530             this.initWithSize(gridSize, texture, flipped);
531     },
532 
533     /**
534      * returns the tile at the given position
535      * @param {cc.Point} pos
536      * @return {cc.Quad3}
537      */
538     tile:function (pos) {
539         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
540             cc.log("cc.TiledGrid3D.tile() : Numbers must be integers");
541 
542         var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
543         var locVertices = this._vertices;
544         return new cc.Quad3(new cc.Vertex3F(locVertices[idx], locVertices[idx + 1], locVertices[idx + 2]),
545             new cc.Vertex3F(locVertices[idx + 3], locVertices[idx + 4], locVertices[idx + 5]),
546             new cc.Vertex3F(locVertices[idx + 6 ], locVertices[idx + 7], locVertices[idx + 8]),
547             new cc.Vertex3F(locVertices[idx + 9], locVertices[idx + 10], locVertices[idx + 11]));
548     },
549 
550     /**
551      * returns the original tile (untransformed) at the given position
552      * @param {cc.Point} pos
553      * @return {cc.Quad3}
554      */
555     originalTile:function (pos) {
556         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
557             cc.log("cc.TiledGrid3D.originalTile() : Numbers must be integers");
558 
559         var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
560         var locOriginalVertices = this._originalVertices;
561         return new cc.Quad3(new cc.Vertex3F(locOriginalVertices[idx], locOriginalVertices[idx + 1], locOriginalVertices[idx + 2]),
562             new cc.Vertex3F(locOriginalVertices[idx + 3], locOriginalVertices[idx + 4], locOriginalVertices[idx + 5]),
563             new cc.Vertex3F(locOriginalVertices[idx + 6 ], locOriginalVertices[idx + 7], locOriginalVertices[idx + 8]),
564             new cc.Vertex3F(locOriginalVertices[idx + 9], locOriginalVertices[idx + 10], locOriginalVertices[idx + 11]));
565     },
566 
567     /**
568      * sets a new tile
569      * @param {cc.Point} pos
570      * @param {cc.Quad3} coords
571      */
572     setTile:function (pos, coords) {
573         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
574             cc.log("cc.TiledGrid3D.setTile() : Numbers must be integers");
575 
576         var idx = (this._gridSize.height * pos.x + pos.y) * 12;
577         var locVertices = this._vertices;
578         locVertices[idx] = coords.bl.x;
579         locVertices[idx + 1] = coords.bl.y;
580         locVertices[idx + 2] = coords.bl.z;
581         locVertices[idx + 3] = coords.br.x;
582         locVertices[idx + 4] = coords.br.y;
583         locVertices[idx + 5] = coords.br.z;
584         locVertices[idx + 6] = coords.tl.x;
585         locVertices[idx + 7] = coords.tl.y;
586         locVertices[idx + 8] = coords.tl.z;
587         locVertices[idx + 9] = coords.tr.x;
588         locVertices[idx + 10] = coords.tr.y;
589         locVertices[idx + 11] = coords.tr.z;
590         this._dirty = true;
591     },
592 
593     blit:function () {
594         var n = this._gridSize.width * this._gridSize.height;
595 
596         this._shaderProgram.use();
597         this._shaderProgram.setUniformsForBuiltins();
598 
599         //
600         // Attributes
601         //
602         var gl = cc._renderContext, locDirty = this._dirty;
603         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS);
604 
605         // position
606         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
607         if (locDirty)
608             gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
609         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 0, this._vertices);
610 
611         // texCoords
612         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
613         if (locDirty)
614             gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
615         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, this._texCoordinates);
616 
617         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
618         if (locDirty)
619             gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
620         gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
621         if (locDirty)
622             this._dirty = false;
623         cc.incrementGLDraws(1);
624     },
625 
626     reuse:function () {
627         if (this._reuseGrid > 0) {
628             var locVertices = this._vertices, locOriginalVertices = this._originalVertices;
629             for (var i = 0; i < locVertices.length; i++)
630                 locOriginalVertices[i] = locVertices[i];
631             --this._reuseGrid;
632         }
633     },
634 
635     calculateVertexPoints:function () {
636         var width = this._texture.pixelsWidth;
637         var height = this._texture.pixelsHeight;
638         var imageH = this._texture.getContentSizeInPixels().height;
639         var locGridSize = this._gridSize;
640 
641         var numQuads = locGridSize.width * locGridSize.height;
642         this._vertices = new Float32Array(numQuads * 12);
643         this._texCoordinates = new Float32Array(numQuads * 8);
644         this._indices = new Uint16Array(numQuads * 6);
645 
646         var gl = cc._renderContext;
647         if(this._verticesBuffer)
648             gl.deleteBuffer(this._verticesBuffer);
649         this._verticesBuffer = gl.createBuffer();
650         if(this._texCoordinateBuffer)
651             gl.deleteBuffer(this._texCoordinateBuffer);
652         this._texCoordinateBuffer = gl.createBuffer();
653         if(this._indicesBuffer)
654             gl.deleteBuffer(this._indicesBuffer);
655         this._indicesBuffer = gl.createBuffer();
656 
657         var x, y, i = 0;
658         var locStep = this._step, locVertices = this._vertices, locTexCoords = this._texCoordinates, locIsTextureFlipped = this._isTextureFlipped;
659         for (x = 0; x < locGridSize.width; x++) {
660             for (y = 0; y < locGridSize.height; y++) {
661                 var x1 = x * locStep.x;
662                 var x2 = x1 + locStep.x;
663                 var y1 = y * locStep.y;
664                 var y2 = y1 + locStep.y;
665 
666                 locVertices[i * 12] = x1;
667                 locVertices[i * 12 + 1] = y1;
668                 locVertices[i * 12 + 2] = 0;
669                 locVertices[i * 12 + 3] = x2;
670                 locVertices[i * 12 + 4] = y1;
671                 locVertices[i * 12 + 5] = 0;
672                 locVertices[i * 12 + 6] = x1;
673                 locVertices[i * 12 + 7] = y2;
674                 locVertices[i * 12 + 8] = 0;
675                 locVertices[i * 12 + 9] = x2;
676                 locVertices[i * 12 + 10] = y2;
677                 locVertices[i * 12 + 11] = 0;
678 
679                 var newY1 = y1;
680                 var newY2 = y2;
681 
682                 if (locIsTextureFlipped) {
683                     newY1 = imageH - y1;
684                     newY2 = imageH - y2;
685                 }
686 
687                 locTexCoords[i * 8] = x1 / width;
688                 locTexCoords[i * 8 + 1] = newY1 / height;
689                 locTexCoords[i * 8 + 2] = x2 / width;
690                 locTexCoords[i * 8 + 3] = newY1 / height;
691                 locTexCoords[i * 8 + 4] = x1 / width;
692                 locTexCoords[i * 8 + 5] = newY2 / height;
693                 locTexCoords[i * 8 + 6] = x2 / width;
694                 locTexCoords[i * 8 + 7] = newY2 / height;
695                 i++;
696             }
697         }
698 
699         var locIndices = this._indices;
700         for (x = 0; x < numQuads; x++) {
701             locIndices[x * 6 + 0] = (x * 4 + 0);
702             locIndices[x * 6 + 1] = (x * 4 + 1);
703             locIndices[x * 6 + 2] = (x * 4 + 2);
704 
705             locIndices[x * 6 + 3] = (x * 4 + 1);
706             locIndices[x * 6 + 4] = (x * 4 + 2);
707             locIndices[x * 6 + 5] = (x * 4 + 3);
708         }
709         this._originalVertices = new Float32Array(this._vertices);
710 
711         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
712         gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
713         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
714         gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
715         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
716         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.DYNAMIC_DRAW);
717         this._dirty = true;
718     }
719 });
720 
721 /**
722  * create one TiledGrid3D object
723  * @deprecated since v3.0, plese use new cc.TiledGrid3D(gridSize, texture, flipped) instead
724  * @param {cc.Size} gridSize
725  * @param {cc.Texture2D} [texture=]
726  * @param {Boolean} [flipped=]
727  * @return {cc.TiledGrid3D}
728  */
729 cc.TiledGrid3D.create = function (gridSize, texture, flipped) {
730     return new cc.TiledGrid3D(gridSize, texture, flipped);
731 };
732