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