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