diff options
| author | Starla Insigna <starla4444@gmail.com> | 2011-07-30 11:19:14 -0400 |
|---|---|---|
| committer | Starla Insigna <starla4444@gmail.com> | 2011-07-30 11:19:14 -0400 |
| commit | 9cd57b731ab1c666d4a1cb725538fdc137763d12 (patch) | |
| tree | 5bac45ae5157a1cb10c6e45500cbf72789917980 /libs/cocos2d/CCTextureAtlas.m | |
| download | cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.gz cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.bz2 cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.zip | |
Initial commit (version 0.2.1)
Diffstat (limited to 'libs/cocos2d/CCTextureAtlas.m')
| -rwxr-xr-x | libs/cocos2d/CCTextureAtlas.m | 369 |
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 | ||
