summary refs log tree commit diff stats
path: root/libs/cocos2d/CCTextureAtlas.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/CCTextureAtlas.m')
-rwxr-xr-xlibs/cocos2d/CCTextureAtlas.m369
1 files changed, 369 insertions, 0 deletions
diff --git a/libs/cocos2d/CCTextureAtlas.m b/libs/cocos2d/CCTextureAtlas.m new file mode 100755 index 0000000..7c7df75 --- /dev/null +++ b/libs/cocos2d/CCTextureAtlas.m
@@ -0,0 +1,369 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28// cocos2d
29#import "CCTextureAtlas.h"
30#import "ccMacros.h"
31#import "CCTexture2D.h"
32#import "CCTextureCache.h"
33
34
35@interface CCTextureAtlas (Private)
36-(void) initIndices;
37@end
38
39//According to some tests GL_TRIANGLE_STRIP is slower, MUCH slower. Probably I'm doing something very wrong
40
41@implementation CCTextureAtlas
42
43@synthesize totalQuads = totalQuads_, capacity = capacity_;
44@synthesize texture = texture_;
45@synthesize quads = quads_;
46
47#pragma mark TextureAtlas - alloc & init
48
49+(id) textureAtlasWithFile:(NSString*) file capacity: (NSUInteger) n
50{
51 return [[[self alloc] initWithFile:file capacity:n] autorelease];
52}
53
54+(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)n
55{
56 return [[[self alloc] initWithTexture:tex capacity:n] autorelease];
57}
58
59-(id) initWithFile:(NSString*)file capacity:(NSUInteger)n
60{
61 // retained in property
62 CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:file];
63 if( tex )
64 return [self initWithTexture:tex capacity:n];
65
66 // else
67 {
68 CCLOG(@"cocos2d: Could not open file: %@", file);
69 [self release];
70 return nil;
71 }
72}
73
74-(id) initWithTexture:(CCTexture2D*)tex capacity:(NSUInteger)n
75{
76 if( (self=[super init]) ) {
77
78 capacity_ = n;
79 totalQuads_ = 0;
80
81 // retained in property
82 self.texture = tex;
83
84 // Re-initialization is not allowed
85 NSAssert(quads_==nil && indices_==nil, @"CCTextureAtlas re-initialization is not allowed");
86
87 quads_ = calloc( sizeof(quads_[0]) * capacity_, 1 );
88 indices_ = calloc( sizeof(indices_[0]) * capacity_ * 6, 1 );
89
90 if( ! ( quads_ && indices_) ) {
91 CCLOG(@"cocos2d: CCTextureAtlas: not enough memory");
92 if( quads_ )
93 free(quads_);
94 if( indices_ )
95 free(indices_);
96 return nil;
97 }
98
99#if CC_USES_VBO
100 // initial binding
101 glGenBuffers(2, &buffersVBO_[0]);
102 dirty_ = YES;
103#endif // CC_USES_VBO
104
105 [self initIndices];
106 }
107
108 return self;
109}
110
111- (NSString*) description
112{
113 return [NSString stringWithFormat:@"<%@ = %08X | totalQuads = %i>", [self class], self, totalQuads_];
114}
115
116-(void) dealloc
117{
118 CCLOGINFO(@"cocos2d: deallocing %@",self);
119
120 free(quads_);
121 free(indices_);
122
123#if CC_USES_VBO
124 glDeleteBuffers(2, buffersVBO_);
125#endif // CC_USES_VBO
126
127
128 [texture_ release];
129
130 [super dealloc];
131}
132
133-(void) initIndices
134{
135 for( NSUInteger i=0;i< capacity_;i++) {
136#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
137 indices_[i*6+0] = i*4+0;
138 indices_[i*6+1] = i*4+0;
139 indices_[i*6+2] = i*4+2;
140 indices_[i*6+3] = i*4+1;
141 indices_[i*6+4] = i*4+3;
142 indices_[i*6+5] = i*4+3;
143#else
144 indices_[i*6+0] = i*4+0;
145 indices_[i*6+1] = i*4+1;
146 indices_[i*6+2] = i*4+2;
147
148 // inverted index. issue #179
149 indices_[i*6+3] = i*4+3;
150 indices_[i*6+4] = i*4+2;
151 indices_[i*6+5] = i*4+1;
152// indices_[i*6+3] = i*4+2;
153// indices_[i*6+4] = i*4+3;
154// indices_[i*6+5] = i*4+1;
155#endif
156 }
157
158#if CC_USES_VBO
159 glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]);
160 glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * capacity_, quads_, GL_DYNAMIC_DRAW);
161 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
162 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_[0]) * capacity_ * 6, indices_, GL_STATIC_DRAW);
163 glBindBuffer(GL_ARRAY_BUFFER, 0);
164 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
165#endif // CC_USES_VBO
166}
167
168#pragma mark TextureAtlas - Update, Insert, Move & Remove
169
170-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger) n
171{
172 NSAssert(n < capacity_, @"updateQuadWithTexture: Invalid index");
173
174 totalQuads_ = MAX( n+1, totalQuads_);
175
176 quads_[n] = *quad;
177
178#if CC_USES_VBO
179 dirty_ = YES;
180#endif
181}
182
183
184-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index
185{
186 NSAssert(index < capacity_, @"insertQuadWithTexture: Invalid index");
187
188 totalQuads_++;
189 NSAssert( totalQuads_ <= capacity_, @"invalid totalQuads");
190
191 // issue #575. index can be > totalQuads
192 NSInteger remaining = (totalQuads_-1) - index;
193
194 // last object doesn't need to be moved
195 if( remaining > 0)
196 // tex coordinates
197 memmove( &quads_[index+1],&quads_[index], sizeof(quads_[0]) * remaining );
198
199 quads_[index] = *quad;
200
201#if CC_USES_VBO
202 dirty_ = YES;
203#endif
204}
205
206
207-(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex
208{
209 NSAssert(newIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index");
210 NSAssert(oldIndex < totalQuads_, @"insertQuadFromIndex:atIndex: Invalid index");
211
212 if( oldIndex == newIndex )
213 return;
214
215 NSUInteger howMany = labs( oldIndex - newIndex);
216 NSUInteger dst = oldIndex;
217 NSUInteger src = oldIndex + 1;
218 if( oldIndex > newIndex) {
219 dst = newIndex+1;
220 src = newIndex;
221 }
222
223 // tex coordinates
224 ccV3F_C4B_T2F_Quad quadsBackup = quads_[oldIndex];
225 memmove( &quads_[dst],&quads_[src], sizeof(quads_[0]) * howMany );
226 quads_[newIndex] = quadsBackup;
227
228#if CC_USES_VBO
229 dirty_ = YES;
230#endif
231}
232
233-(void) removeQuadAtIndex:(NSUInteger) index
234{
235 NSAssert(index < totalQuads_, @"removeQuadAtIndex: Invalid index");
236
237 NSUInteger remaining = (totalQuads_-1) - index;
238
239
240 // last object doesn't need to be moved
241 if( remaining )
242 // tex coordinates
243 memmove( &quads_[index],&quads_[index+1], sizeof(quads_[0]) * remaining );
244
245 totalQuads_--;
246
247#if CC_USES_VBO
248 dirty_ = YES;
249#endif
250}
251
252-(void) removeAllQuads
253{
254 totalQuads_ = 0;
255}
256
257#pragma mark TextureAtlas - Resize
258
259-(BOOL) resizeCapacity: (NSUInteger) newCapacity
260{
261 if( newCapacity == capacity_ )
262 return YES;
263
264 // update capacity and totolQuads
265 totalQuads_ = MIN(totalQuads_,newCapacity);
266 capacity_ = newCapacity;
267
268 void * tmpQuads = realloc( quads_, sizeof(quads_[0]) * capacity_ );
269 void * tmpIndices = realloc( indices_, sizeof(indices_[0]) * capacity_ * 6 );
270
271 if( ! ( tmpQuads && tmpIndices) ) {
272 CCLOG(@"cocos2d: CCTextureAtlas: not enough memory");
273 if( tmpQuads )
274 free(tmpQuads);
275 else
276 free(quads_);
277
278 if( tmpIndices )
279 free(tmpIndices);
280 else
281 free(indices_);
282
283 indices_ = nil;
284 quads_ = nil;
285 capacity_ = totalQuads_ = 0;
286 return NO;
287 }
288
289 quads_ = tmpQuads;
290 indices_ = tmpIndices;
291
292 [self initIndices];
293
294#if CC_USES_VBO
295 dirty_ = YES;
296#endif
297 return YES;
298}
299
300#pragma mark TextureAtlas - Drawing
301
302-(void) drawQuads
303{
304 [self drawNumberOfQuads: totalQuads_ fromIndex:0];
305}
306
307-(void) drawNumberOfQuads: (NSUInteger) n
308{
309 [self drawNumberOfQuads:n fromIndex:0];
310}
311
312-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start
313{
314 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
315 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
316 // Unneeded states: -
317
318 glBindTexture(GL_TEXTURE_2D, [texture_ name]);
319#define kQuadSize sizeof(quads_[0].bl)
320#if CC_USES_VBO
321 glBindBuffer(GL_ARRAY_BUFFER, buffersVBO_[0]);
322
323 // XXX: update is done in draw... perhaps it should be done in a timer
324 if (dirty_) {
325 glBufferSubData(GL_ARRAY_BUFFER, sizeof(quads_[0])*start, sizeof(quads_[0]) * n , &quads_[start] );
326 dirty_ = NO;
327 }
328
329 // vertices
330 glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices));
331
332 // colors
333 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors));
334
335 // tex coords
336 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords));
337
338 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
339#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
340 glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) );
341#else
342 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) );
343#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
344
345 glBindBuffer(GL_ARRAY_BUFFER, 0);
346 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
347#else // ! CC_USES_VBO
348
349 NSUInteger offset = (NSUInteger)quads_;
350 // vertex
351 NSUInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
352 glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) (offset + diff) );
353 // color
354 diff = offsetof( ccV3F_C4B_T2F, colors);
355 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff));
356
357 // tex coords
358 diff = offsetof( ccV3F_C4B_T2F, texCoords);
359 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff));
360
361#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
362 glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, indices_ + start * 6 );
363#else
364 glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indices_ + start * 6 );
365#endif
366
367#endif // CC_USES_VBO
368}
369@end