1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 var cc = cc = cc || {};
 28 
 29 /** Base class for other
 30  */
 31 cc.GridBase = cc.Class.extend({
 32     _active:null,
 33     _reuseGrid:null,
 34     _gridSize:null,
 35     _texture:null,
 36     _step:cc.p(0, 0),
 37     _grabber:null,
 38     _isTextureFlipped:null,
 39     /** wheter or not the grid is active */
 40     isActive:function () {
 41         return this._active;
 42     },
 43     setActive:function (active) {
 44         this._active = active;
 45         if (!active) {
 46             var director = cc.Director.getInstance();
 47             var proj = director.getProjection();
 48             director.setProjection(proj);
 49         }
 50     },
 51 
 52     /** number of times that the grid will be reused */
 53     getReuseGrid:function () {
 54         return this._reuseGrid;
 55     },
 56     setReuseGrid:function (reuseGrid) {
 57         this._reuseGrid = reuseGrid;
 58     },
 59 
 60     /** size of the grid */
 61     getGridSize:function () {
 62         return this._gridSize;
 63     },
 64     setGridSize:function (gridSize) {
 65         this._gridSize.x = parseInt(gridSize.x);
 66         this._gridSize.y = parseInt(gridSize.y);
 67     },
 68 
 69     /** pixels between the grids */
 70     getStep:function () {
 71         return this._step;
 72     },
 73     setStep:function (step) {
 74         this._step = step;
 75     },
 76 
 77     /** is texture flipped */
 78     isTextureFlipped:function () {
 79         return this._isTextureFlipped;
 80     },
 81     setIsTextureFlipped:function (flipped) {
 82         if (this._isTextureFlipped != flipped) {
 83             this._isTextureFlipped = flipped;
 84             this.calculateVertexPoints();
 85         }
 86     },
 87 
 88     initWithSize:function (gridSize, texture, flipped) {
 89         var argnum = arguments.length;
 90         if (argnum = 1) {
 91             var director = cc.Director.getInstance();
 92             var s = director.getWinSizeInPixels();
 93 
 94             var POTWide = cc.NextPOT(s.width);
 95             var POTHigh = cc.NextPOT(s.height);
 96 
 97             // we only use rgba8888
 98             var format = cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888;
 99 
100             var pTextureTemp = new cc.Texture2D();
101             pTextureTemp.initWithData(format, POTWide, POTHigh, s);
102             if (!pTextureTemp) {
103                 cc.log("cocos2d: CCGrid: error creating texture");
104                 return false;
105             }
106             texture = pTextureTemp;
107 
108             flipped = false;
109         }
110 
111 
112         var ret = true;
113 
114         this._active = false;
115         this._reuseGrid = 0;
116         this._gridSize = gridSize;
117         this._texture = texture;
118         this._isTextureFlipped = flipped;
119 
120         var texSize = this._texture.getContentSizeInPixels();
121         this._step.x = texSize.width / this._gridSize.x;
122         this._step.y = texSize.height / this._gridSize.y;
123 
124         this._grabber = new cc.Grabber();
125         if (this._grabber) {
126             this._grabber.grab(this._texture);
127         }
128         else {
129             ret = false;
130         }
131 
132 
133         this.calculateVertexPoints();
134 
135         return ret;
136 
137     },
138 
139     beforeDraw:function () {
140         this.set2DProjection();
141         this._grabber.beforeRender(this._texture);
142     },
143     afterDraw:function (target) {
144         this._grabber.afterRender(this._texture);
145 
146         this.set3DProjection();
147 
148         if (target.getCamera().getDirty()) {
149             var offset = target.getAnchorPointInPixels();
150 
151             //
152             // XXX: Camera should be applied in the AnchorPoint
153             //
154             //todo gl
155             //ccglTranslate(offset.x, offset.y, 0);
156             target.getCamera().locate();
157             //ccglTranslate(-offset.x, -offset.y, 0);
158         }
159 //todo gl
160         //glBindTexture(GL_TEXTURE_2D, this._texture.getName());
161 
162         // restore projection for default FBO .fixed bug #543 #544
163         //cc.Director.getInstance().setProjection(cc.Director.getInstance().getProjection());
164         //cc.Director.getInstance().applyOrientation();
165         this.blit();
166     },
167     blit:function () {
168         cc.Assert(0, "");
169     },
170     reuse:function () {
171         cc.Assert(0, "");
172     },
173     calculateVertexPoints:function () {
174         cc.Assert(0, "");
175     },
176     set2DProjection:function () {
177         var winSize = cc.Director.getInstance().getWinSizeInPixels();
178 
179         //todo gl
180         /* glViewport(0, 0, (GLsizei)(size.width * CC_CONTENT_SCALE_FACTOR()), (GLsizei)(size.height * CC_CONTENT_SCALE_FACTOR()) );
181          kmGLMatrixMode(KM_GL_PROJECTION);
182          kmGLLoadIdentity();
183 
184          kmMat4 orthoMatrix;
185          kmMat4OrthographicProjection(&orthoMatrix, 0, size.width * CC_CONTENT_SCALE_FACTOR(), 0, size.height * CC_CONTENT_SCALE_FACTOR(), -1, 1);
186          kmGLMultMatrix( &orthoMatrix );
187 
188          kmGLMatrixMode(KM_GL_MODELVIEW);
189          kmGLLoadIdentity();
190 
191 
192          ccSetProjectionMatrixDirty();*/
193     }
194 });
195 cc.GridBase.create = function () {
196     return new cc.GridBase();
197 };
198 
199 /**
200  cc.Grid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z
201  */
202 cc.Grid3D = cc.GridBase.extend({
203     _texCoordinates:null,
204     _vertices:null,
205     _originalVertices:null,
206     _indices:null,
207     /** returns the vertex at a given position */
208     vertex:function (pos) {
209         var index = (pos.x * (this._gridSize.y + 1) + pos.y) * 3;
210         var vertArray = this._vertices;
211 
212         var vert = new cc.Vertex3F(vertArray[index], vertArray[index + 1], vertArray[index + 2]);
213 
214         return vert;
215     },
216     /** returns the original (non-transformed) vertex at a given position */
217     originalVertex:function (pos) {
218         var index = (pos.x * (this._gridSize.y + 1) + pos.y) * 3;
219         var vertArray = this._originalVertices;
220 
221         var vert = new cc.Vertex3F(vertArray[index], vertArray[index + 1], vertArray[index + 2]);
222 
223         return vert;
224     },
225     /** sets a new vertex at a given position */
226     setVertex:function (pos, vertex) {
227         var index = (pos.x * (this._gridSize.y + 1) + pos.y) * 3;
228         var vertArray = this._vertices;
229         vertArray[index] = vertex.x;
230         vertArray[index + 1] = vertex.y;
231         vertArray[index + 2] = vertex.z;
232     },
233 
234     blit:function () {
235         var n = this._gridSize.x * this._gridSize.y;
236 
237         // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
238         // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
239         // Unneeded states: GL_COLOR_ARRAY
240         //todo gl
241         /*glDisableClientState(GL_COLOR_ARRAY);
242 
243          glVertexPointer(3, GL_FLOAT, 0, this._vertices);
244          glTexCoordPointer(2, GL_FLOAT, 0, this._texCoordinates);
245          glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, this._indices);
246 
247          // restore default GL state
248          glEnableClientState(GL_COLOR_ARRAY);*/
249     },
250     reuse:function () {
251         if (this._reuseGrid > 0) {
252             --this._reuseGrid;
253         }
254     },
255     calculateVertexPoints:function () {
256         var width = this._texture.getPixelsWide();
257         var height = this._texture.getPixelsHigh();
258         var imageH = this._texture.getContentSizeInPixels().height;
259 
260         var numQuads = this._gridSize.x * this._gridSize.y;
261 
262         this._vertices = [];
263         this._originalVertices = [];
264         this._texCoordinates = [];
265         this._indices = [];
266 
267         var vertArray = this._vertices;
268         var texArray = this._texCoordinates;
269         var idxArray = this._indices;
270 
271         var x, y;
272 
273         for (x = 0; x < this._gridSize.x; x++) {
274             for (y = 0; y < this._gridSize.y; y++) {
275                 var x1 = x * this._step.x;
276                 var x2 = x1 + this._step.x;
277                 var y1 = y * this._step.y;
278                 var y2 = y1 + this._step.y;
279 
280                 vertArray[x * y] = x1;
281                 vertArray[x * y + 1] = y1;
282                 vertArray[x * y + 2] = 0;
283                 vertArray[x * y + 3] = x2;
284                 vertArray[x * y + 4] = y1;
285                 vertArray[x * y + 5] = 0;
286                 vertArray[x * y + 6] = x1;
287                 vertArray[x * y + 7] = y2;
288                 vertArray[x * y + 8] = 0;
289                 vertArray[x * y + 9] = x2;
290                 vertArray[x * y + 10] = y2;
291                 vertArray[x * y + 11] = 0;
292 
293                 var newY1 = y1;
294                 var newY2 = y2;
295 
296                 if (this._isTextureFlipped) {
297                     newY1 = imageH - y1;
298                     newY2 = imageH - y2;
299                 }
300 
301                 texArray[x * y + 12] = x1 / width;
302                 texArray[x * y + 13] = newY1 / height;
303                 texArray[x * y + 14] = x2 / width;
304                 texArray[x * y + 15] = newY1 / height;
305                 texArray[x * y + 16] = x1 / width;
306                 texArray[x * y + 17] = newY2 / height;
307                 texArray[x * y + 18] = x2 / width;
308                 texArray[x * y + 19] = newY2 / height;
309             }
310         }
311 
312         for (x = 0; x < numQuads; x++) {
313             idxArray[x * 6 + 0] = x * 4 + 0;
314             idxArray[x * 6 + 1] = x * 4 + 1;
315             idxArray[x * 6 + 2] = x * 4 + 2;
316 
317             idxArray[x * 6 + 3] = x * 4 + 1;
318             idxArray[x * 6 + 4] = x * 4 + 2;
319             idxArray[x * 6 + 5] = x * 4 + 3;
320         }
321 
322     }
323 });
324 
325 cc.Grid3D.create = function (gridSize, texture, flipped) {
326 
327 };
328 
329 /**
330  cc.TiledGrid3D is a 3D grid implementation. It differs from Grid3D in that
331  the tiles can be separated from the grid.
332  */
333 cc.TiledGrid3D = cc.GridBase.extend({
334     _texCoordinates:null,
335     _vertices:null,
336     _originalVertices:null,
337     _indices:null,
338     /** returns the tile at the given position */
339     tile:function (pos) {
340         var idx = (this._gridSize.y * pos.x + pos.y) * 4 * 3;
341         var vertArray = this._vertices;
342         var ret = new cc.Quad3();
343         return ret;
344     },
345     /** returns the original tile (untransformed) at the given position */
346     originalTile:function (pos) {
347         var idx = (this._gridSize.y * pos.x + pos.y) * 4 * 3;
348         var vertArray = this._originalVertices;
349 
350         var ret = new cc.Quad3(vertArray[idx], vertArray[idx + 1], vertArray[idx + 2], vertArray[idx + 3]);
351 
352         return ret;
353     },
354     /** sets a new tile */
355     setTile:function (pos, coords) {
356         var idx = (this._gridSize.y * pos.x + pos.y) * 4 * 3;
357         var vertArray = this._vertices;
358         vertArray[idx] = coords;
359     },
360 
361     blit:function () {
362         var n = this._gridSize.x * this._gridSize.y;
363 
364         // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
365         // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
366         // Unneeded states: GL_COLOR_ARRAY
367         //todo gl
368         /*glDisableClientState(GL_COLOR_ARRAY);
369 
370          glVertexPointer(3, GL_FLOAT, 0, this._vertices);
371          glTexCoordPointer(2, GL_FLOAT, 0, this._texCoordinates);
372          glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, this._indices);
373 
374          // restore default GL state
375          glEnableClientState(GL_COLOR_ARRAY);*/
376     },
377     reuse:function () {
378         if (this._reuseGrid > 0) {
379             var numQuads = this._gridSize.x * this._gridSize.y;
380             for (var i = 0, len = numQuads.length * 12; i < len; i++) {
381                 this._originalVertices.push(this._vertices[i])
382             }
383             //todo fix
384             //memcpy(this._originalVertices, this._vertices, numQuads * 12 * sizeof(GLfloat));
385             --this._reuseGrid;
386         }
387     },
388     calculateVertexPoints:function () {
389         var width = this._texture.getPixelsWide();
390         var height = this._texture.getPixelsHigh();
391         var imageH = this._texture.getContentSizeInPixels().height;
392 
393         var numQuads = this._gridSize.x * this._gridSize.y;
394 
395         this._vertices = [];
396         this._originalVertices = [];
397         this._texCoordinates = [];
398         this._indices = [];
399 
400         var vertArray = this._vertices;
401         var texArray = this._texCoordinates;
402         var idxArray = this._indices;
403 
404         var x, y;
405 
406         for (x = 0; x < this._gridSize.x; x++) {
407             for (y = 0; y < this._gridSize.y; y++) {
408                 var x1 = x * this._step.x;
409                 var x2 = x1 + this._step.x;
410                 var y1 = y * this._step.y;
411                 var y2 = y1 + this._step.y;
412 
413                 vertArray[x * y] = x1;
414                 vertArray[x * y + 1] = y1;
415                 vertArray[x * y + 2] = 0;
416                 vertArray[x * y + 3] = x2;
417                 vertArray[x * y + 4] = y1;
418                 vertArray[x * y + 5] = 0;
419                 vertArray[x * y + 6] = x1;
420                 vertArray[x * y + 7] = y2;
421                 vertArray[x * y + 8] = 0;
422                 vertArray[x * y + 9] = x2;
423                 vertArray[x * y + 10] = y2;
424                 vertArray[x * y + 11] = 0;
425                 var newY1 = y1;
426                 var newY2 = y2;
427 
428                 if (this._isTextureFlipped) {
429                     newY1 = imageH - y1;
430                     newY2 = imageH - y2;
431                 }
432 
433                 texArray[x * y + 12] = x1 / width;
434                 texArray[x * y + 13] = newY1 / height;
435                 texArray[x * y + 14] = x2 / width;
436                 texArray[x * y + 15] = newY1 / height;
437                 texArray[x * y + 16] = x1 / width;
438                 texArray[x * y + 17] = newY2 / height;
439                 texArray[x * y + 18] = x2 / width;
440                 texArray[x * y + 19] = newY2 / height;
441             }
442         }
443 
444         for (x = 0; x < numQuads; x++) {
445             idxArray[x * 6 + 0] = x * 4 + 0;
446             idxArray[x * 6 + 1] = x * 4 + 1;
447             idxArray[x * 6 + 2] = x * 4 + 2;
448 
449             idxArray[x * 6 + 3] = x * 4 + 1;
450             idxArray[x * 6 + 4] = x * 4 + 2;
451             idxArray[x * 6 + 5] = x * 4 + 3;
452         }
453         for (var i = 0, len = numQuads.length * 12; i < len; i++) {
454             this._originalVertices.push(this._vertices[i])
455         }
456         //todo fix
457         //memcpy(this._originalVertices, this._vertices, numQuads * 12 * sizeof(GLfloat));
458     }
459 });
460 
461 cc.TiledGrid3D.create = function (gridSize, texture, flipped) {
462     var ret = new cc.TiledGrid3D();
463     ret.initWithSize(gridSize, texture, flipped)
464     return ret;
465 };
466