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 whether or not the texture is flipped
142      * @return {Boolean}
143      */
144     isTextureFlipped:function () {
145         return this._isTextureFlipped;
146     },
147 
148     /**
149      * set whether 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         //this.set2DProjection();    //TODO why?
214         this._grabber.beforeRender(this._texture);
215     },
216 
217     afterDraw:function (target) {
218         this._grabber.afterRender(this._texture);
219 
220         // restore projection
221         //cc.director.setProjection(this._directorProjection);
222 
223         if (target && target.getCamera().isDirty()) {
224             var offset = target.getAnchorPointInPoints();
225 
226             //TODO hack
227             var stackMatrix = target._renderCmd._stackMatrix;
228             //
229             // XXX: Camera should be applied in the AnchorPoint
230             //
231             //cc.kmGLTranslatef(offset.x, offset.y, 0);
232             var translation = new cc.kmMat4();
233             cc.kmMat4Translation(translation, offset.x, offset.y, 0);
234             cc.kmMat4Multiply(stackMatrix, stackMatrix, translation);
235 
236             //target.getCamera().locate();
237             target._camera._locateForRenderer(stackMatrix);
238 
239             //cc.kmGLTranslatef(-offset.x, -offset.y, 0);
240             cc.kmMat4Translation(translation, -offset.x, -offset.y, 0);
241             cc.kmMat4Multiply(stackMatrix, stackMatrix, translation);
242         }
243 
244         cc.glBindTexture2D(this._texture);
245         this.blit(target);
246     },
247 
248     blit:function () {
249         cc.log("cc.GridBase.blit(): Shall be overridden in subclass.");
250     },
251 
252     reuse:function () {
253         cc.log("cc.GridBase.reuse(): Shall be overridden in subclass.");
254     },
255 
256     calculateVertexPoints:function () {
257         cc.log("cc.GridBase.calculateVertexPoints(): Shall be overridden in subclass.");
258     },
259 
260     set2DProjection:function () {
261         var winSize = cc.director.getWinSizeInPixels();
262 
263         var gl = cc._renderContext;
264         gl.viewport(0, 0, winSize.width , winSize.height);
265         cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
266         cc.kmGLLoadIdentity();
267 
268         var orthoMatrix = new cc.kmMat4();
269         cc.kmMat4OrthographicProjection(orthoMatrix, 0, winSize.width, 0, winSize.height, -1, 1);
270         cc.kmGLMultMatrix(orthoMatrix);
271 
272         cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
273         cc.kmGLLoadIdentity();
274         cc.setProjectionMatrixDirty()
275     }
276 });
277 
278 /**
279  * create one cc.GridBase Object
280  * @deprecated
281  * @param {cc.Size} gridSize
282  * @param {cc.Texture2D} [texture=]
283  * @param {Boolean} [flipped=]
284  * @return {cc.GridBase}
285  */
286 cc.GridBase.create = function (gridSize, texture, flipped) {
287     return new cc.GridBase(gridSize, texture, flipped);
288 };
289 
290 /**
291  * cc.Grid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z
292  * @class
293  * @extends cc.GridBase
294  */
295 cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
296     _texCoordinates:null,
297     _vertices:null,
298     _originalVertices:null,
299     _indices:null,
300 
301     _texCoordinateBuffer:null,
302     _verticesBuffer:null,
303     _indicesBuffer:null,
304 
305     /**
306      * create one Grid3D object
307      * Constructor of cc.Grid3D
308      * @param {cc.Size} gridSize
309      * @param {cc.Texture2D} [texture=]
310      * @param {Boolean} [flipped=]
311      */
312     ctor:function (gridSize, texture, flipped) {
313         cc.GridBase.prototype.ctor.call(this);
314         this._texCoordinates=null;
315         this._vertices=null;
316         this._originalVertices=null;
317         this._indices=null;
318 
319         this._texCoordinateBuffer=null;
320         this._verticesBuffer=null;
321         this._indicesBuffer=null;
322 
323         if(gridSize !== undefined)
324             this.initWithSize(gridSize, texture, flipped);
325     },
326 
327     /**
328      * returns the vertex at a given position
329      * @param {cc.Point} pos
330      * @return {cc.Vertex3F}
331      */
332     vertex:function (pos) {
333         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
334             cc.log("cc.Grid3D.vertex() : Numbers must be integers");
335         var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
336         var locVertices = this._vertices;
337         return new cc.Vertex3F(locVertices[index], locVertices[index + 1], locVertices[index + 2]);
338     },
339 
340     /**
341      * returns the original (non-transformed) vertex at a given position
342      * @param {cc.Point} pos
343      * @return {cc.Vertex3F}
344      */
345     originalVertex:function (pos) {
346         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
347             cc.log("cc.Grid3D.originalVertex() : Numbers must be integers");
348         var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
349         var locOriginalVertices = this._originalVertices;
350         return new cc.Vertex3F(locOriginalVertices[index], locOriginalVertices[index + 1], locOriginalVertices[index + 2]);
351     },
352 
353     /**
354      * sets a new vertex at a given position
355      * @param {cc.Point} pos
356      * @param {cc.Vertex3F} vertex
357      */
358     setVertex:function (pos, vertex) {
359         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
360             cc.log("cc.Grid3D.setVertex() : Numbers must be integers");
361         var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
362         var vertArray = this._vertices;
363         vertArray[index] = vertex.x;
364         vertArray[index + 1] = vertex.y;
365         vertArray[index + 2] = vertex.z;
366         this._dirty = true;
367     },
368 
369     blit:function (target) {
370         var n = this._gridSize.width * this._gridSize.height;
371         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS);
372         this._shaderProgram.use();
373         //this._shaderProgram.setUniformsForBuiltins();
374         this._shaderProgram._setUniformForMVPMatrixWithMat4(target._renderCmd._stackMatrix);
375 
376         var gl = cc._renderContext, locDirty = this._dirty;
377         //
378         // Attributes
379         //
380         // position
381         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
382         if (locDirty)
383             gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
384         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 0, 0);
385 
386         // texCoords
387         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
388         if (locDirty)
389             gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
390         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, 0);
391 
392         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
393         if (locDirty)
394             gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
395         gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
396         if (locDirty)
397             this._dirty = false;
398         cc.incrementGLDraws(1);
399     },
400 
401     reuse:function () {
402         if (this._reuseGrid > 0) {
403             var locOriginalVertices = this._originalVertices, locVertices = this._vertices;
404             for (var i = 0, len =  this._vertices.length; i < len; i++)
405                 locOriginalVertices[i] = locVertices[i];
406             --this._reuseGrid;
407         }
408     },
409 
410     calculateVertexPoints:function () {
411         var gl = cc._renderContext;
412 
413         var width = this._texture.pixelsWidth;
414         var height = this._texture.pixelsHeight;
415         var imageH = this._texture.getContentSizeInPixels().height;
416         var locGridSize = this._gridSize;
417 
418         var numOfPoints = (locGridSize.width + 1) * (locGridSize.height + 1);
419         this._vertices = new Float32Array(numOfPoints * 3);
420         this._texCoordinates = new Float32Array(numOfPoints * 2);
421         this._indices = new Uint16Array(locGridSize.width * locGridSize.height * 6);
422 
423         if(this._verticesBuffer)
424             gl.deleteBuffer(this._verticesBuffer);
425         this._verticesBuffer = gl.createBuffer();
426         if(this._texCoordinateBuffer)
427             gl.deleteBuffer(this._texCoordinateBuffer);
428         this._texCoordinateBuffer = gl.createBuffer();
429         if(this._indicesBuffer)
430             gl.deleteBuffer(this._indicesBuffer);
431         this._indicesBuffer = gl.createBuffer();
432 
433         var x, y, i, locIndices = this._indices, locTexCoordinates = this._texCoordinates;
434         var locIsTextureFlipped = this._isTextureFlipped, locVertices = this._vertices;
435         for (x = 0; x < locGridSize.width; ++x) {
436             for (y = 0; y < locGridSize.height; ++y) {
437                 var idx = (y * locGridSize.width) + x;
438                 var x1 = x * this._step.x;
439                 var x2 = x1 + this._step.x;
440                 var y1 = y * this._step.y;
441                 var y2 = y1 + this._step.y;
442 
443                 var a = (x * (locGridSize.height + 1) + y);
444                 var b = ((x + 1) * (locGridSize.height + 1) + y);
445                 var c = ((x + 1) * (locGridSize.height + 1) + (y + 1));
446                 var d = (x * (locGridSize.height + 1) + (y + 1));
447 
448                 locIndices[idx * 6] = a;
449                 locIndices[idx * 6 + 1] = b;
450                 locIndices[idx * 6 + 2] = d;
451                 locIndices[idx * 6 + 3] = b;
452                 locIndices[idx * 6 + 4] = c;
453                 locIndices[idx * 6 + 5] = d;
454 
455                 var l1 = [a * 3, b * 3, c * 3, d * 3];
456                 var e = {x:x1, y:y1, z:0};   //new cc.Vertex3F(x1, y1, 0);
457                 var f = {x:x2, y:y1, z:0};   //new cc.Vertex3F(x2, y1, 0);
458                 var g = {x:x2, y:y2, z:0};   // new cc.Vertex3F(x2, y2, 0);
459                 var h = {x:x1, y:y2, z:0};   //new cc.Vertex3F(x1, y2, 0);
460 
461                 var l2 = [e, f, g, h];
462                 var tex1 = [a * 2, b * 2, c * 2, d * 2];
463                 var tex2 = [cc.p(x1, y1), cc.p(x2, y1), cc.p(x2, y2), cc.p(x1, y2)];
464                 for (i = 0; i < 4; ++i) {
465                     locVertices[l1[i]] = l2[i].x;
466                     locVertices[l1[i] + 1] = l2[i].y;
467                     locVertices[l1[i] + 2] = l2[i].z;
468                     locTexCoordinates[tex1[i]] = tex2[i].x / width;
469                     if (locIsTextureFlipped)
470                         locTexCoordinates[tex1[i] + 1] = (imageH - tex2[i].y) / height;
471                     else
472                         locTexCoordinates[tex1[i] + 1] = tex2[i].y / height;
473                 }
474             }
475         }
476         this._originalVertices = new Float32Array(this._vertices);
477 
478         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
479         gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
480         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
481         gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
482         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
483         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
484         this._dirty = true;
485     }
486 });
487 
488 /**
489  * create one Grid3D object
490  * @deprecated
491  * @param {cc.Size} gridSize
492  * @param {cc.Texture2D} [texture=]
493  * @param {Boolean} [flipped=]
494  * @return {cc.Grid3D}
495  */
496 cc.Grid3D.create = function (gridSize, texture, flipped) {
497     return new cc.Grid3D(gridSize, texture, flipped);
498 };
499 
500 /**
501  * cc.TiledGrid3D is a 3D grid implementation. It differs from Grid3D in that   <br/>
502  * the tiles can be separated from the grid.
503  * @class
504  * @extends cc.GridBase
505  */
506 cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
507     _texCoordinates:null,
508     _vertices:null,
509     _originalVertices:null,
510     _indices:null,
511 
512     _texCoordinateBuffer:null,
513     _verticesBuffer:null,
514     _indicesBuffer:null,
515 
516     /**
517      * create one TiledGrid3D object
518      * Constructor of cc.TiledGrid3D
519      * @param {cc.Size} gridSize
520      * @param {cc.Texture2D} [texture=]
521      * @param {Boolean} [flipped=]
522      */
523     ctor:function (gridSize, texture, flipped) {
524         cc.GridBase.prototype.ctor.call(this);
525         this._texCoordinates=null;
526         this._vertices=null;
527         this._originalVertices=null;
528         this._indices=null;
529 
530         this._texCoordinateBuffer=null;
531         this._verticesBuffer=null;
532         this._indicesBuffer=null;
533 
534         if(gridSize !== undefined)
535             this.initWithSize(gridSize, texture, flipped);
536     },
537 
538     /**
539      * returns the tile at the given position
540      * @param {cc.Point} pos
541      * @return {cc.Quad3}
542      */
543     tile:function (pos) {
544         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
545             cc.log("cc.TiledGrid3D.tile() : Numbers must be integers");
546 
547         var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
548         var locVertices = this._vertices;
549         return new cc.Quad3(new cc.Vertex3F(locVertices[idx], locVertices[idx + 1], locVertices[idx + 2]),
550             new cc.Vertex3F(locVertices[idx + 3], locVertices[idx + 4], locVertices[idx + 5]),
551             new cc.Vertex3F(locVertices[idx + 6 ], locVertices[idx + 7], locVertices[idx + 8]),
552             new cc.Vertex3F(locVertices[idx + 9], locVertices[idx + 10], locVertices[idx + 11]));
553     },
554 
555     /**
556      * returns the original tile (untransformed) at the given position
557      * @param {cc.Point} pos
558      * @return {cc.Quad3}
559      */
560     originalTile:function (pos) {
561         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
562             cc.log("cc.TiledGrid3D.originalTile() : Numbers must be integers");
563 
564         var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
565         var locOriginalVertices = this._originalVertices;
566         return new cc.Quad3(new cc.Vertex3F(locOriginalVertices[idx], locOriginalVertices[idx + 1], locOriginalVertices[idx + 2]),
567             new cc.Vertex3F(locOriginalVertices[idx + 3], locOriginalVertices[idx + 4], locOriginalVertices[idx + 5]),
568             new cc.Vertex3F(locOriginalVertices[idx + 6 ], locOriginalVertices[idx + 7], locOriginalVertices[idx + 8]),
569             new cc.Vertex3F(locOriginalVertices[idx + 9], locOriginalVertices[idx + 10], locOriginalVertices[idx + 11]));
570     },
571 
572     /**
573      * sets a new tile
574      * @param {cc.Point} pos
575      * @param {cc.Quad3} coords
576      */
577     setTile:function (pos, coords) {
578         if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
579             cc.log("cc.TiledGrid3D.setTile() : Numbers must be integers");
580 
581         var idx = (this._gridSize.height * pos.x + pos.y) * 12;
582         var locVertices = this._vertices;
583         locVertices[idx] = coords.bl.x;
584         locVertices[idx + 1] = coords.bl.y;
585         locVertices[idx + 2] = coords.bl.z;
586         locVertices[idx + 3] = coords.br.x;
587         locVertices[idx + 4] = coords.br.y;
588         locVertices[idx + 5] = coords.br.z;
589         locVertices[idx + 6] = coords.tl.x;
590         locVertices[idx + 7] = coords.tl.y;
591         locVertices[idx + 8] = coords.tl.z;
592         locVertices[idx + 9] = coords.tr.x;
593         locVertices[idx + 10] = coords.tr.y;
594         locVertices[idx + 11] = coords.tr.z;
595         this._dirty = true;
596     },
597 
598     blit:function (target) {
599         var n = this._gridSize.width * this._gridSize.height;
600 
601         this._shaderProgram.use();
602         this._shaderProgram._setUniformForMVPMatrixWithMat4(target._renderCmd._stackMatrix);
603         //this._shaderProgram.setUniformsForBuiltins();
604 
605         //
606         // Attributes
607         //
608         var gl = cc._renderContext, locDirty = this._dirty;
609         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS);
610 
611         // position
612         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
613         if (locDirty)
614             gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
615         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 0, this._vertices);
616 
617         // texCoords
618         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
619         if (locDirty)
620             gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
621         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, this._texCoordinates);
622 
623         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
624         if (locDirty)
625             gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
626         gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
627         if (locDirty)
628             this._dirty = false;
629         cc.incrementGLDraws(1);
630     },
631 
632     reuse:function () {
633         if (this._reuseGrid > 0) {
634             var locVertices = this._vertices, locOriginalVertices = this._originalVertices;
635             for (var i = 0; i < locVertices.length; i++)
636                 locOriginalVertices[i] = locVertices[i];
637             --this._reuseGrid;
638         }
639     },
640 
641     calculateVertexPoints:function () {
642         var width = this._texture.pixelsWidth;
643         var height = this._texture.pixelsHeight;
644         var imageH = this._texture.getContentSizeInPixels().height;
645         var locGridSize = this._gridSize;
646 
647         var numQuads = locGridSize.width * locGridSize.height;
648         this._vertices = new Float32Array(numQuads * 12);
649         this._texCoordinates = new Float32Array(numQuads * 8);
650         this._indices = new Uint16Array(numQuads * 6);
651 
652         var gl = cc._renderContext;
653         if(this._verticesBuffer)
654             gl.deleteBuffer(this._verticesBuffer);
655         this._verticesBuffer = gl.createBuffer();
656         if(this._texCoordinateBuffer)
657             gl.deleteBuffer(this._texCoordinateBuffer);
658         this._texCoordinateBuffer = gl.createBuffer();
659         if(this._indicesBuffer)
660             gl.deleteBuffer(this._indicesBuffer);
661         this._indicesBuffer = gl.createBuffer();
662 
663         var x, y, i = 0;
664         var locStep = this._step, locVertices = this._vertices, locTexCoords = this._texCoordinates, locIsTextureFlipped = this._isTextureFlipped;
665         for (x = 0; x < locGridSize.width; x++) {
666             for (y = 0; y < locGridSize.height; y++) {
667                 var x1 = x * locStep.x;
668                 var x2 = x1 + locStep.x;
669                 var y1 = y * locStep.y;
670                 var y2 = y1 + locStep.y;
671 
672                 locVertices[i * 12] = x1;
673                 locVertices[i * 12 + 1] = y1;
674                 locVertices[i * 12 + 2] = 0;
675                 locVertices[i * 12 + 3] = x2;
676                 locVertices[i * 12 + 4] = y1;
677                 locVertices[i * 12 + 5] = 0;
678                 locVertices[i * 12 + 6] = x1;
679                 locVertices[i * 12 + 7] = y2;
680                 locVertices[i * 12 + 8] = 0;
681                 locVertices[i * 12 + 9] = x2;
682                 locVertices[i * 12 + 10] = y2;
683                 locVertices[i * 12 + 11] = 0;
684 
685                 var newY1 = y1;
686                 var newY2 = y2;
687 
688                 if (locIsTextureFlipped) {
689                     newY1 = imageH - y1;
690                     newY2 = imageH - y2;
691                 }
692 
693                 locTexCoords[i * 8] = x1 / width;
694                 locTexCoords[i * 8 + 1] = newY1 / height;
695                 locTexCoords[i * 8 + 2] = x2 / width;
696                 locTexCoords[i * 8 + 3] = newY1 / height;
697                 locTexCoords[i * 8 + 4] = x1 / width;
698                 locTexCoords[i * 8 + 5] = newY2 / height;
699                 locTexCoords[i * 8 + 6] = x2 / width;
700                 locTexCoords[i * 8 + 7] = newY2 / height;
701                 i++;
702             }
703         }
704 
705         var locIndices = this._indices;
706         for (x = 0; x < numQuads; x++) {
707             locIndices[x * 6 + 0] = (x * 4 + 0);
708             locIndices[x * 6 + 1] = (x * 4 + 1);
709             locIndices[x * 6 + 2] = (x * 4 + 2);
710 
711             locIndices[x * 6 + 3] = (x * 4 + 1);
712             locIndices[x * 6 + 4] = (x * 4 + 2);
713             locIndices[x * 6 + 5] = (x * 4 + 3);
714         }
715         this._originalVertices = new Float32Array(this._vertices);
716 
717         gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
718         gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
719         gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
720         gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
721         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
722         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.DYNAMIC_DRAW);
723         this._dirty = true;
724     }
725 });
726 
727 /**
728  * create one TiledGrid3D object
729  * @deprecated since v3.0, please use new cc.TiledGrid3D(gridSize, texture, flipped) instead
730  * @param {cc.Size} gridSize
731  * @param {cc.Texture2D} [texture=]
732  * @param {Boolean} [flipped=]
733  * @return {cc.TiledGrid3D}
734  */
735 cc.TiledGrid3D.create = function (gridSize, texture, flipped) {
736     return new cc.TiledGrid3D(gridSize, texture, flipped);
737 };
738