summary refs log tree commit diff stats
path: root/libs/cocos2d/CCParticleSystemQuad.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/CCParticleSystemQuad.m')
-rwxr-xr-xlibs/cocos2d/CCParticleSystemQuad.m318
1 files changed, 318 insertions, 0 deletions
diff --git a/libs/cocos2d/CCParticleSystemQuad.m b/libs/cocos2d/CCParticleSystemQuad.m new file mode 100755 index 0000000..4916964 --- /dev/null +++ b/libs/cocos2d/CCParticleSystemQuad.m
@@ -0,0 +1,318 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Leonardo Kasperavičius
5 *
6 * Copyright (c) 2008-2010 Ricardo Quesada
7 * Copyright (c) 2011 Zynga Inc.
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
30// opengl
31#import "Platforms/CCGL.h"
32
33// cocos2d
34#import "ccConfig.h"
35#import "CCParticleSystemQuad.h"
36#import "CCTextureCache.h"
37#import "ccMacros.h"
38#import "CCSpriteFrame.h"
39
40// support
41#import "Support/OpenGL_Internal.h"
42#import "Support/CGPointExtension.h"
43
44@implementation CCParticleSystemQuad
45
46
47// overriding the init method
48-(id) initWithTotalParticles:(NSUInteger) numberOfParticles
49{
50 // base initialization
51 if( (self=[super initWithTotalParticles:numberOfParticles]) ) {
52
53 // allocating data space
54 quads_ = calloc( sizeof(quads_[0]) * totalParticles, 1 );
55 indices_ = calloc( sizeof(indices_[0]) * totalParticles * 6, 1 );
56
57 if( !quads_ || !indices_) {
58 NSLog(@"cocos2d: Particle system: not enough memory");
59 if( quads_ )
60 free( quads_ );
61 if(indices_)
62 free(indices_);
63
64 [self release];
65 return nil;
66 }
67
68 // initialize only once the texCoords and the indices
69 [self initTexCoordsWithRect:CGRectMake(0, 0, [texture_ pixelsWide], [texture_ pixelsHigh])];
70 [self initIndices];
71
72#if CC_USES_VBO
73 // create the VBO buffer
74 glGenBuffers(1, &quadsID_);
75
76 // initial binding
77 glBindBuffer(GL_ARRAY_BUFFER, quadsID_);
78 glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0])*totalParticles, quads_,GL_DYNAMIC_DRAW);
79 glBindBuffer(GL_ARRAY_BUFFER, 0);
80#endif
81 }
82
83 return self;
84}
85
86-(void) dealloc
87{
88 free(quads_);
89 free(indices_);
90#if CC_USES_VBO
91 glDeleteBuffers(1, &quadsID_);
92#endif
93
94 [super dealloc];
95}
96
97// pointRect is in Points coordinates.
98-(void) initTexCoordsWithRect:(CGRect)pointRect
99{
100 // convert to pixels coords
101 CGRect rect = CGRectMake(
102 pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(),
103 pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(),
104 pointRect.size.width * CC_CONTENT_SCALE_FACTOR(),
105 pointRect.size.height * CC_CONTENT_SCALE_FACTOR() );
106
107 GLfloat wide = [texture_ pixelsWide];
108 GLfloat high = [texture_ pixelsHigh];
109
110#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
111 GLfloat left = (rect.origin.x*2+1) / (wide*2);
112 GLfloat bottom = (rect.origin.y*2+1) / (high*2);
113 GLfloat right = left + (rect.size.width*2-2) / (wide*2);
114 GLfloat top = bottom + (rect.size.height*2-2) / (high*2);
115#else
116 GLfloat left = rect.origin.x / wide;
117 GLfloat bottom = rect.origin.y / high;
118 GLfloat right = left + rect.size.width / wide;
119 GLfloat top = bottom + rect.size.height / high;
120#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
121
122 // Important. Texture in cocos2d are inverted, so the Y component should be inverted
123 CC_SWAP( top, bottom);
124
125 for(NSUInteger i=0; i<totalParticles; i++) {
126 // bottom-left vertex:
127 quads_[i].bl.texCoords.u = left;
128 quads_[i].bl.texCoords.v = bottom;
129 // bottom-right vertex:
130 quads_[i].br.texCoords.u = right;
131 quads_[i].br.texCoords.v = bottom;
132 // top-left vertex:
133 quads_[i].tl.texCoords.u = left;
134 quads_[i].tl.texCoords.v = top;
135 // top-right vertex:
136 quads_[i].tr.texCoords.u = right;
137 quads_[i].tr.texCoords.v = top;
138 }
139}
140
141-(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect
142{
143 // Only update the texture if is different from the current one
144 if( [texture name] != [texture_ name] )
145 [super setTexture:texture];
146
147 [self initTexCoordsWithRect:rect];
148}
149
150-(void) setTexture:(CCTexture2D *)texture
151{
152 CGSize s = [texture contentSize];
153 [self setTexture:texture withRect:CGRectMake(0,0, s.width, s.height)];
154}
155
156-(void) setDisplayFrame:(CCSpriteFrame *)spriteFrame
157{
158
159 NSAssert( CGPointEqualToPoint( spriteFrame.offsetInPixels , CGPointZero ), @"QuadParticle only supports SpriteFrames with no offsets");
160
161 // update texture before updating texture rect
162 if ( spriteFrame.texture.name != texture_.name )
163 [self setTexture: spriteFrame.texture];
164}
165
166-(void) initIndices
167{
168 for( NSUInteger i=0;i< totalParticles;i++) {
169 const NSUInteger i6 = i*6;
170 const NSUInteger i4 = i*4;
171 indices_[i6+0] = (GLushort) i4+0;
172 indices_[i6+1] = (GLushort) i4+1;
173 indices_[i6+2] = (GLushort) i4+2;
174
175 indices_[i6+5] = (GLushort) i4+1;
176 indices_[i6+4] = (GLushort) i4+2;
177 indices_[i6+3] = (GLushort) i4+3;
178 }
179}
180
181-(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos
182{
183 // colors
184 ccV2F_C4B_T2F_Quad *quad = &(quads_[particleIdx]);
185
186 ccColor4B color = { p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255};
187 quad->bl.colors = color;
188 quad->br.colors = color;
189 quad->tl.colors = color;
190 quad->tr.colors = color;
191
192 // vertices
193 GLfloat size_2 = p->size/2;
194 if( p->rotation ) {
195 GLfloat x1 = -size_2;
196 GLfloat y1 = -size_2;
197
198 GLfloat x2 = size_2;
199 GLfloat y2 = size_2;
200 GLfloat x = newPos.x;
201 GLfloat y = newPos.y;
202
203 GLfloat r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation);
204 GLfloat cr = cosf(r);
205 GLfloat sr = sinf(r);
206 GLfloat ax = x1 * cr - y1 * sr + x;
207 GLfloat ay = x1 * sr + y1 * cr + y;
208 GLfloat bx = x2 * cr - y1 * sr + x;
209 GLfloat by = x2 * sr + y1 * cr + y;
210 GLfloat cx = x2 * cr - y2 * sr + x;
211 GLfloat cy = x2 * sr + y2 * cr + y;
212 GLfloat dx = x1 * cr - y2 * sr + x;
213 GLfloat dy = x1 * sr + y2 * cr + y;
214
215 // bottom-left
216 quad->bl.vertices.x = ax;
217 quad->bl.vertices.y = ay;
218
219 // bottom-right vertex:
220 quad->br.vertices.x = bx;
221 quad->br.vertices.y = by;
222
223 // top-left vertex:
224 quad->tl.vertices.x = dx;
225 quad->tl.vertices.y = dy;
226
227 // top-right vertex:
228 quad->tr.vertices.x = cx;
229 quad->tr.vertices.y = cy;
230 } else {
231 // bottom-left vertex:
232 quad->bl.vertices.x = newPos.x - size_2;
233 quad->bl.vertices.y = newPos.y - size_2;
234
235 // bottom-right vertex:
236 quad->br.vertices.x = newPos.x + size_2;
237 quad->br.vertices.y = newPos.y - size_2;
238
239 // top-left vertex:
240 quad->tl.vertices.x = newPos.x - size_2;
241 quad->tl.vertices.y = newPos.y + size_2;
242
243 // top-right vertex:
244 quad->tr.vertices.x = newPos.x + size_2;
245 quad->tr.vertices.y = newPos.y + size_2;
246 }
247}
248
249-(void) postStep
250{
251#if CC_USES_VBO
252 glBindBuffer(GL_ARRAY_BUFFER, quadsID_);
253 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quads_[0])*particleCount, quads_);
254 glBindBuffer(GL_ARRAY_BUFFER, 0);
255#endif
256}
257
258// overriding draw method
259-(void) draw
260{
261 [super draw];
262
263 // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
264 // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
265 // Unneeded states: -
266
267 glBindTexture(GL_TEXTURE_2D, [texture_ name]);
268
269#define kQuadSize sizeof(quads_[0].bl)
270
271#if CC_USES_VBO
272 glBindBuffer(GL_ARRAY_BUFFER, quadsID_);
273
274 glVertexPointer(2,GL_FLOAT, kQuadSize, 0);
275
276 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof(ccV2F_C4B_T2F,colors) );
277
278 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof(ccV2F_C4B_T2F,texCoords) );
279#else // vertex array list
280
281 NSUInteger offset = (NSUInteger) quads_;
282
283 // vertex
284 NSUInteger diff = offsetof( ccV2F_C4B_T2F, vertices);
285 glVertexPointer(2,GL_FLOAT, kQuadSize, (GLvoid*) (offset+diff) );
286
287 // color
288 diff = offsetof( ccV2F_C4B_T2F, colors);
289 glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff));
290
291 // tex coords
292 diff = offsetof( ccV2F_C4B_T2F, texCoords);
293 glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff));
294
295#endif // ! CC_USES_VBO
296
297 BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST;
298 if( newBlend )
299 glBlendFunc( blendFunc_.src, blendFunc_.dst );
300
301 NSAssert( particleIdx == particleCount, @"Abnormal error in particle quad");
302 glDrawElements(GL_TRIANGLES, (GLsizei) particleIdx*6, GL_UNSIGNED_SHORT, indices_);
303
304 // restore blend state
305 if( newBlend )
306 glBlendFunc( CC_BLEND_SRC, CC_BLEND_DST );
307
308#if CC_USES_VBO
309 glBindBuffer(GL_ARRAY_BUFFER, 0);
310#endif
311
312 // restore GL default state
313 // -
314}
315
316@end
317
318