summary refs log tree commit diff stats
path: root/libs/cocos2d/CCGrid.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/CCGrid.m')
-rwxr-xr-xlibs/cocos2d/CCGrid.m571
1 files changed, 571 insertions, 0 deletions
diff --git a/libs/cocos2d/CCGrid.m b/libs/cocos2d/CCGrid.m new file mode 100755 index 0000000..c2ed19d --- /dev/null +++ b/libs/cocos2d/CCGrid.m
@@ -0,0 +1,571 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 On-Core
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Availability.h>
28
29#import "ccMacros.h"
30#import "CCGrid.h"
31#import "CCTexture2D.h"
32#import "CCDirector.h"
33#import "CCGrabber.h"
34
35#import "Platforms/CCGL.h"
36#import "Support/CGPointExtension.h"
37#import "Support/ccUtils.h"
38
39#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
40#import "Platforms/iOS/CCDirectorIOS.h"
41#endif // __IPHONE_OS_VERSION_MAX_ALLOWED
42
43#pragma mark -
44#pragma mark CCGridBase
45
46@implementation CCGridBase
47
48@synthesize reuseGrid = reuseGrid_;
49@synthesize texture = texture_;
50@synthesize grabber = grabber_;
51@synthesize gridSize = gridSize_;
52@synthesize step = step_;
53
54+(id) gridWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped
55{
56 return [[[self alloc] initWithSize:gridSize texture:texture flippedTexture:flipped] autorelease];
57}
58
59+(id) gridWithSize:(ccGridSize)gridSize
60{
61 return [[(CCGridBase*)[self alloc] initWithSize:gridSize] autorelease];
62}
63
64-(id) initWithSize:(ccGridSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped
65{
66 if( (self=[super init]) ) {
67
68 active_ = NO;
69 reuseGrid_ = 0;
70 gridSize_ = gridSize;
71
72 self.texture = texture;
73 isTextureFlipped_ = flipped;
74
75 CGSize texSize = [texture_ contentSizeInPixels];
76 step_.x = texSize.width / gridSize_.x;
77 step_.y = texSize.height / gridSize_.y;
78
79 grabber_ = [[CCGrabber alloc] init];
80 [grabber_ grab:texture_];
81
82 [self calculateVertexPoints];
83 }
84 return self;
85}
86
87-(id)initWithSize:(ccGridSize)gSize
88{
89 CCDirector *director = [CCDirector sharedDirector];
90 CGSize s = [director winSizeInPixels];
91
92 unsigned long POTWide = ccNextPOT(s.width);
93 unsigned long POTHigh = ccNextPOT(s.height);
94
95#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
96 EAGLView *glview = [[CCDirector sharedDirector] openGLView];
97 NSString *pixelFormat = [glview pixelFormat];
98
99 CCTexture2DPixelFormat format = [pixelFormat isEqualToString: kEAGLColorFormatRGB565] ? kCCTexture2DPixelFormat_RGB565 : kCCTexture2DPixelFormat_RGBA8888;
100#else
101 CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888;
102#endif
103
104 void *data = calloc((int)(POTWide * POTHigh * 4), 1);
105 if( ! data ) {
106 CCLOG(@"cocos2d: CCGrid: not enough memory");
107 [self release];
108 return nil;
109 }
110
111 CCTexture2D *texture = [[CCTexture2D alloc] initWithData:data pixelFormat:format pixelsWide:POTWide pixelsHigh:POTHigh contentSize:s];
112 free( data );
113
114 if( ! texture ) {
115 CCLOG(@"cocos2d: CCGrid: error creating texture");
116 [self release];
117 return nil;
118 }
119
120 self = [self initWithSize:gSize texture:texture flippedTexture:NO];
121
122 [texture release];
123
124 return self;
125}
126- (NSString*) description
127{
128 return [NSString stringWithFormat:@"<%@ = %08X | Dimensions = %ix%i>", [self class], self, gridSize_.x, gridSize_.y];
129}
130
131- (void) dealloc
132{
133 CCLOGINFO(@"cocos2d: deallocing %@", self);
134
135 [self setActive: NO];
136
137 [texture_ release];
138 [grabber_ release];
139 [super dealloc];
140}
141
142// properties
143-(BOOL) active
144{
145 return active_;
146}
147
148-(void) setActive:(BOOL)active
149{
150 active_ = active;
151 if( ! active ) {
152 CCDirector *director = [CCDirector sharedDirector];
153 ccDirectorProjection proj = [director projection];
154 [director setProjection:proj];
155 }
156}
157
158-(BOOL) isTextureFlipped
159{
160 return isTextureFlipped_;
161}
162
163-(void) setIsTextureFlipped:(BOOL)flipped
164{
165 if( isTextureFlipped_ != flipped ) {
166 isTextureFlipped_ = flipped;
167 [self calculateVertexPoints];
168 }
169}
170
171// This routine can be merged with Director
172#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
173-(void)applyLandscape
174{
175 CCDirector *director = [CCDirector sharedDirector];
176
177 CGSize winSize = [director displaySizeInPixels];
178 float w = winSize.width / 2;
179 float h = winSize.height / 2;
180
181 ccDeviceOrientation orientation = [director deviceOrientation];
182
183 switch (orientation) {
184 case CCDeviceOrientationLandscapeLeft:
185 glTranslatef(w,h,0);
186 glRotatef(-90,0,0,1);
187 glTranslatef(-h,-w,0);
188 break;
189 case CCDeviceOrientationLandscapeRight:
190 glTranslatef(w,h,0);
191 glRotatef(90,0,0,1);
192 glTranslatef(-h,-w,0);
193 break;
194 case CCDeviceOrientationPortraitUpsideDown:
195 glTranslatef(w,h,0);
196 glRotatef(180,0,0,1);
197 glTranslatef(-w,-h,0);
198 break;
199 default:
200 break;
201 }
202}
203#endif
204
205-(void)set2DProjection
206{
207 CGSize winSize = [[CCDirector sharedDirector] winSizeInPixels];
208
209 glLoadIdentity();
210 glViewport(0, 0, winSize.width, winSize.height);
211 glMatrixMode(GL_PROJECTION);
212 glLoadIdentity();
213 ccglOrtho(0, winSize.width, 0, winSize.height, -1024, 1024);
214 glMatrixMode(GL_MODELVIEW);
215}
216
217// This routine can be merged with Director
218-(void)set3DProjection
219{
220 CCDirector *director = [CCDirector sharedDirector];
221
222 CGSize winSize = [director displaySizeInPixels];
223
224 glViewport(0, 0, winSize.width, winSize.height);
225 glMatrixMode(GL_PROJECTION);
226 glLoadIdentity();
227 gluPerspective(60, (GLfloat)winSize.width/winSize.height, 0.5f, 1500.0f);
228
229 glMatrixMode(GL_MODELVIEW);
230 glLoadIdentity();
231 gluLookAt( winSize.width/2, winSize.height/2, [director getZEye],
232 winSize.width/2, winSize.height/2, 0,
233 0.0f, 1.0f, 0.0f
234 );
235}
236
237-(void)beforeDraw
238{
239 [self set2DProjection];
240 [grabber_ beforeRender:texture_];
241}
242
243-(void)afterDraw:(CCNode *)target
244{
245 [grabber_ afterRender:texture_];
246
247 [self set3DProjection];
248#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
249 [self applyLandscape];
250#endif
251
252 if( target.camera.dirty ) {
253
254 CGPoint offset = [target anchorPointInPixels];
255
256 //
257 // XXX: Camera should be applied in the AnchorPoint
258 //
259 ccglTranslate(offset.x, offset.y, 0);
260 [target.camera locate];
261 ccglTranslate(-offset.x, -offset.y, 0);
262 }
263
264 glBindTexture(GL_TEXTURE_2D, texture_.name);
265
266 [self blit];
267}
268
269-(void)blit
270{
271 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
272}
273
274-(void)reuse
275{
276 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
277}
278
279-(void)calculateVertexPoints
280{
281 [NSException raise:@"GridBase" format:@"Abstract class needs implementation"];
282}
283
284@end
285
286////////////////////////////////////////////////////////////
287
288#pragma mark -
289#pragma mark CCGrid3D
290@implementation CCGrid3D
291
292-(void)dealloc
293{
294 free(texCoordinates);
295 free(vertices);
296 free(indices);
297 free(originalVertices);
298 [super dealloc];
299}
300
301-(void)blit
302{
303 NSInteger n = gridSize_.x * gridSize_.y;
304
305 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
306 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
307 // Unneeded states: GL_COLOR_ARRAY
308 glDisableClientState(GL_COLOR_ARRAY);
309
310 glVertexPointer(3, GL_FLOAT, 0, vertices);
311 glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
312 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, indices);
313
314 // restore GL default state
315 glEnableClientState(GL_COLOR_ARRAY);
316}
317
318-(void)calculateVertexPoints
319{
320 float width = (float)texture_.pixelsWide;
321 float height = (float)texture_.pixelsHigh;
322 float imageH = texture_.contentSizeInPixels.height;
323
324 int x, y, i;
325
326 vertices = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
327 originalVertices = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
328 texCoordinates = malloc((gridSize_.x+1)*(gridSize_.y+1)*sizeof(CGPoint));
329 indices = malloc(gridSize_.x*gridSize_.y*sizeof(GLushort)*6);
330
331 float *vertArray = (float*)vertices;
332 float *texArray = (float*)texCoordinates;
333 GLushort *idxArray = (GLushort *)indices;
334
335 for( x = 0; x < gridSize_.x; x++ )
336 {
337 for( y = 0; y < gridSize_.y; y++ )
338 {
339 NSInteger idx = (y * gridSize_.x) + x;
340
341 float x1 = x * step_.x;
342 float x2 = x1 + step_.x;
343 float y1 = y * step_.y;
344 float y2 = y1 + step_.y;
345
346 GLushort a = x * (gridSize_.y+1) + y;
347 GLushort b = (x+1) * (gridSize_.y+1) + y;
348 GLushort c = (x+1) * (gridSize_.y+1) + (y+1);
349 GLushort d = x * (gridSize_.y+1) + (y+1);
350
351 GLushort tempidx[6] = { a, b, d, b, c, d };
352
353 memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort));
354
355 int l1[4] = { a*3, b*3, c*3, d*3 };
356 ccVertex3F e = {x1,y1,0};
357 ccVertex3F f = {x2,y1,0};
358 ccVertex3F g = {x2,y2,0};
359 ccVertex3F h = {x1,y2,0};
360
361 ccVertex3F l2[4] = { e, f, g, h };
362
363 int tex1[4] = { a*2, b*2, c*2, d*2 };
364 CGPoint tex2[4] = { ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2) };
365
366 for( i = 0; i < 4; i++ )
367 {
368 vertArray[ l1[i] ] = l2[i].x;
369 vertArray[ l1[i] + 1 ] = l2[i].y;
370 vertArray[ l1[i] + 2 ] = l2[i].z;
371
372 texArray[ tex1[i] ] = tex2[i].x / width;
373 if( isTextureFlipped_ )
374 texArray[ tex1[i] + 1 ] = (imageH - tex2[i].y) / height;
375 else
376 texArray[ tex1[i] + 1 ] = tex2[i].y / height;
377 }
378 }
379 }
380
381 memcpy(originalVertices, vertices, (gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
382}
383
384-(ccVertex3F)vertex:(ccGridSize)pos
385{
386 NSInteger index = (pos.x * (gridSize_.y+1) + pos.y) * 3;
387 float *vertArray = (float *)vertices;
388
389 ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] };
390
391 return vert;
392}
393
394-(ccVertex3F)originalVertex:(ccGridSize)pos
395{
396 NSInteger index = (pos.x * (gridSize_.y+1) + pos.y) * 3;
397 float *vertArray = (float *)originalVertices;
398
399 ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] };
400
401 return vert;
402}
403
404-(void)setVertex:(ccGridSize)pos vertex:(ccVertex3F)vertex
405{
406 NSInteger index = (pos.x * (gridSize_.y+1) + pos.y) * 3;
407 float *vertArray = (float *)vertices;
408 vertArray[index] = vertex.x;
409 vertArray[index+1] = vertex.y;
410 vertArray[index+2] = vertex.z;
411}
412
413-(void)reuse
414{
415 if ( reuseGrid_ > 0 )
416 {
417 memcpy(originalVertices, vertices, (gridSize_.x+1)*(gridSize_.y+1)*sizeof(ccVertex3F));
418 reuseGrid_--;
419 }
420}
421
422@end
423
424////////////////////////////////////////////////////////////
425
426#pragma mark -
427#pragma mark CCTiledGrid3D
428
429@implementation CCTiledGrid3D
430
431-(void)dealloc
432{
433 free(texCoordinates);
434 free(vertices);
435 free(indices);
436 free(originalVertices);
437 [super dealloc];
438}
439
440-(void)blit
441{
442 NSInteger n = gridSize_.x * gridSize_.y;
443
444 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
445 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
446 // Unneeded states: GL_COLOR_ARRAY
447 glDisableClientState(GL_COLOR_ARRAY);
448
449 glVertexPointer(3, GL_FLOAT, 0, vertices);
450 glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
451 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, indices);
452
453 // restore default GL state
454 glEnableClientState(GL_COLOR_ARRAY);
455}
456
457-(void)calculateVertexPoints
458{
459 float width = (float)texture_.pixelsWide;
460 float height = (float)texture_.pixelsHigh;
461 float imageH = texture_.contentSizeInPixels.height;
462
463 NSInteger numQuads = gridSize_.x * gridSize_.y;
464
465 vertices = malloc(numQuads*12*sizeof(GLfloat));
466 originalVertices = malloc(numQuads*12*sizeof(GLfloat));
467 texCoordinates = malloc(numQuads*8*sizeof(GLfloat));
468 indices = malloc(numQuads*6*sizeof(GLushort));
469
470 float *vertArray = (float*)vertices;
471 float *texArray = (float*)texCoordinates;
472 GLushort *idxArray = (GLushort *)indices;
473
474 int x, y;
475
476 for( x = 0; x < gridSize_.x; x++ )
477 {
478 for( y = 0; y < gridSize_.y; y++ )
479 {
480 float x1 = x * step_.x;
481 float x2 = x1 + step_.x;
482 float y1 = y * step_.y;
483 float y2 = y1 + step_.y;
484
485 *vertArray++ = x1;
486 *vertArray++ = y1;
487 *vertArray++ = 0;
488 *vertArray++ = x2;
489 *vertArray++ = y1;
490 *vertArray++ = 0;
491 *vertArray++ = x1;
492 *vertArray++ = y2;
493 *vertArray++ = 0;
494 *vertArray++ = x2;
495 *vertArray++ = y2;
496 *vertArray++ = 0;
497
498 float newY1 = y1;
499 float newY2 = y2;
500
501 if( isTextureFlipped_ ) {
502 newY1 = imageH - y1;
503 newY2 = imageH - y2;
504 }
505
506 *texArray++ = x1 / width;
507 *texArray++ = newY1 / height;
508 *texArray++ = x2 / width;
509 *texArray++ = newY1 / height;
510 *texArray++ = x1 / width;
511 *texArray++ = newY2 / height;
512 *texArray++ = x2 / width;
513 *texArray++ = newY2 / height;
514 }
515 }
516
517 for( x = 0; x < numQuads; x++)
518 {
519 idxArray[x*6+0] = x*4+0;
520 idxArray[x*6+1] = x*4+1;
521 idxArray[x*6+2] = x*4+2;
522
523 idxArray[x*6+3] = x*4+1;
524 idxArray[x*6+4] = x*4+2;
525 idxArray[x*6+5] = x*4+3;
526 }
527
528 memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat));
529}
530
531-(void)setTile:(ccGridSize)pos coords:(ccQuad3)coords
532{
533 NSInteger idx = (gridSize_.y * pos.x + pos.y) * 4 * 3;
534 float *vertArray = (float*)vertices;
535 memcpy(&vertArray[idx], &coords, sizeof(ccQuad3));
536}
537
538-(ccQuad3)originalTile:(ccGridSize)pos
539{
540 NSInteger idx = (gridSize_.y * pos.x + pos.y) * 4 * 3;
541 float *vertArray = (float*)originalVertices;
542
543 ccQuad3 ret;
544 memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
545
546 return ret;
547}
548
549-(ccQuad3)tile:(ccGridSize)pos
550{
551 NSInteger idx = (gridSize_.y * pos.x + pos.y) * 4 * 3;
552 float *vertArray = (float*)vertices;
553
554 ccQuad3 ret;
555 memcpy(&ret, &vertArray[idx], sizeof(ccQuad3));
556
557 return ret;
558}
559
560-(void)reuse
561{
562 if ( reuseGrid_ > 0 )
563 {
564 NSInteger numQuads = gridSize_.x * gridSize_.y;
565
566 memcpy(originalVertices, vertices, numQuads*12*sizeof(GLfloat));
567 reuseGrid_--;
568 }
569}
570
571@end