/* * cocos2d for iPhone: http://www.cocos2d-iphone.org * * Copyright (c) 2008-2010 Ricardo Quesada * Copyright (c) 2011 Zynga Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #import #import "CCParticleSystemPoint.h" #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED // opengl #import "Platforms/CCGL.h" // cocos2d #import "CCTextureCache.h" #import "ccMacros.h" // support #import "Support/OpenGL_Internal.h" #import "Support/CGPointExtension.h" @implementation CCParticleSystemPoint -(id) initWithTotalParticles:(NSUInteger) numberOfParticles { if( (self=[super initWithTotalParticles:numberOfParticles]) ) { vertices = malloc( sizeof(ccPointSprite) * totalParticles ); if( ! vertices ) { NSLog(@"cocos2d: Particle system: not enough memory"); [self release]; return nil; } #if CC_USES_VBO glGenBuffers(1, &verticesID); // initial binding glBindBuffer(GL_ARRAY_BUFFER, verticesID); glBufferData(GL_ARRAY_BUFFER, sizeof(ccPointSprite)*totalParticles, vertices, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); #endif } return self; } -(void) dealloc { free(vertices); #if CC_USES_VBO glDeleteBuffers(1, &verticesID); #endif [super dealloc]; } -(void) updateQuadWithParticle:(tCCParticle*)p newPosition:(CGPoint)newPos { // place vertices and colos in array vertices[particleIdx].pos = (ccVertex2F) {newPos.x, newPos.y}; vertices[particleIdx].size = p->size; ccColor4B color = { p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255 }; vertices[particleIdx].color = color; } -(void) postStep { #if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, verticesID); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(ccPointSprite)*particleCount, vertices); glBindBuffer(GL_ARRAY_BUFFER, 0); #endif } -(void) draw { [super draw]; if (particleIdx==0) return; // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY // Unneeded states: GL_TEXTURE_COORD_ARRAY glDisableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_2D, texture_.name); glEnable(GL_POINT_SPRITE_OES); glTexEnvi( GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE ); #define kPointSize sizeof(vertices[0]) #if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, verticesID); glVertexPointer(2,GL_FLOAT, kPointSize, 0); glColorPointer(4, GL_UNSIGNED_BYTE, kPointSize, (GLvoid*) offsetof(ccPointSprite, color) ); glEnableClientState(GL_POINT_SIZE_ARRAY_OES); glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) offsetof(ccPointSprite, size) ); #else // Uses Vertex Array List int offset = (int)vertices; glVertexPointer(2,GL_FLOAT, kPointSize, (GLvoid*) offset); int diff = offsetof(ccPointSprite, color); glColorPointer(4, GL_UNSIGNED_BYTE, kPointSize, (GLvoid*) (offset+diff)); glEnableClientState(GL_POINT_SIZE_ARRAY_OES); diff = offsetof(ccPointSprite, size); glPointSizePointerOES(GL_FLOAT, kPointSize, (GLvoid*) (offset+diff)); #endif BOOL newBlend = blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST; if( newBlend ) glBlendFunc( blendFunc_.src, blendFunc_.dst ); glDrawArrays(GL_POINTS, 0, particleIdx); // restore blend state if( newBlend ) glBlendFunc( CC_BLEND_SRC, CC_BLEND_DST); #if CC_USES_VBO // unbind VBO buffer glBindBuffer(GL_ARRAY_BUFFER, 0); #endif glDisableClientState(GL_POINT_SIZE_ARRAY_OES); glDisable(GL_POINT_SPRITE_OES); // restore GL default state glEnableClientState(GL_TEXTURE_COORD_ARRAY); } #pragma mark Non supported properties // // SPIN IS NOT SUPPORTED // -(void) setStartSpin:(float)a { NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); [super setStartSpin:a]; } -(void) setStartSpinVar:(float)a { NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); [super setStartSpin:a]; } -(void) setEndSpin:(float)a { NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); [super setStartSpin:a]; } -(void) setEndSpinVar:(float)a { NSAssert(a == 0, @"PointParticleSystem doesn't support spinning"); [super setStartSpin:a]; } // // SIZE > 64 IS NOT SUPPORTED // -(void) setStartSize:(float)size { NSAssert(size >= 0 && size <= CC_MAX_PARTICLE_SIZE, @"PointParticleSystem only supports 0 <= size <= 64"); [super setStartSize:size]; } -(void) setEndSize:(float)size { NSAssert( (size == kCCParticleStartSizeEqualToEndSize) || ( size >= 0 && size <= CC_MAX_PARTICLE_SIZE), @"PointParticleSystem only supports 0 <= size <= 64"); [super setEndSize:size]; } @end #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) @implementation CCParticleSystemPoint @end #endif // __MAC_OS_X_VERSION_MAX_ALLOWED