Over a million developers have joined DZone.

Particles Set Free! High Performance Particles for Swift Developers

· Java Zone

Learn more about how the Java language, tools and frameworks have been the foundation of countless enterprise systems, brought to you in partnership with Salesforce.

If you've been interested in the seemingly endless iterations of my GPU based particle systems for iOS but a bit scared of all that slightly arcane Metal boilerplate code, you may be interested to learn that I've finally packaged up all that Metal code into a single class to make implementing high performance  particle systems as easy as a few lines of code for Swift developers.
My new class is called ParticleLab, with exception of its shader, Particles.metal, it's the only thing that needs to be copied into a new project. Implementation is super simple: just instantiate an instance:

let particleLab = ParticleLab()

Then, when you're ready, add it as a sub-layer to your view's layer:

view.layer.addSublayer(particleLab)

ParticleLab allows up to four gravity wells that have two properties: mass and spin. The former defines the force with which particles are attracted to a gravity well and the latter defines how much particles spin around it. Gravity wells aren't normally rendered, but they can be made visible (which may be useful during development) with a simple flag: 

particleLab.showGravityWellPositions = true

Each time ParticleLab completes a step, you may want to perform some action, for example update the position of your gravity wells. To do this, you can have a class implement ParticleLabDelegate and set itself as the instance'sparticleLabDelegate. The protocol only contains one method: particleLabDidUpdate():

particleLab.particleLabDelegate = self

To update gravity wells, ParticleLab exposes a setGravityWellProperties. This requires a GravityWell enum to define which of the four gravity wells you want to update followed by normalised positions (0,0 is top left and 1,1 is bottom right) and mass and spin values. To get the effect in the video above, my particleLabDidUpdate() method looks like this:

    var gravityWellAngle: Float = 0
    let floatPi = Float(M_PI)
    
    func particleLabDidUpdate()
    {
        gravityWellAngle = gravityWellAngle + 0.01
        
        particleLab.setGravityWellProperties(gravityWell: .One,
            normalisedPositionX: 0.5 + 0.1 * sin(gravityWellAngle + floatPi * 0.5),
            normalisedPositionY: 0.5 + 0.1 * cos(gravityWellAngle + floatPi * 0.5), mass: 11, spin: 13)
        
        particleLab.setGravityWellProperties(gravityWell: .Four,
            normalisedPositionX: 0.5 + 0.1 * sin(gravityWellAngle + floatPi * 1.5),
            normalisedPositionY: 0.5 + 0.1 * cos(gravityWellAngle + floatPi * 1.5), mass: 11, spin: 13)
        
        particleLab.setGravityWellProperties(gravityWell: .Two,
            normalisedPositionX: 0.5 + (0.35 + sin(gravityWellAngle * 1.7)) * cos(gravityWellAngle / 1.3),
            normalisedPositionY: 0.5 + (0.35 + sin(gravityWellAngle * 1.7)) * sin(gravityWellAngle / 1.3), mass: 26, spin: -16)
        
        particleLab.setGravityWellProperties(gravityWell: .Three,
            normalisedPositionX: 0.5 + (0.35 + sin(gravityWellAngle * 1.7)) * cos(gravityWellAngle / 1.3 + floatPi),
            normalisedPositionY: 0.5 + (0.35 + sin(gravityWellAngle * 1.7)) * sin(gravityWellAngle / 1.3 + floatPi), mass: 26, spin: -16)

    }

...and that's pretty much it! There's no reason why you couldn't control the gravity wells by touch events or an audio feed to get some amazing effects. 
ParticleLab is currently hard coded to 2,000,000 particles and runs nicely on my iPad Air 2 at 60fps. I'd consider this a beta release - there are still properties to expose and error handling to add, but the basic Metal particle engine is pretty solid. I have no idea how nicely this will play embedded in another app, especially if that app is quite intensive.
I'd really love to hear of any interesting projects using ParticleLab, please reach out to me via Twitter where I am @FlexMonkey
The source code is available at my GitHub repository here. Enjoy!
Stop Press! The first collaborative project has already kicked off! I've been working with some of the AudioKit team on an audio-driven particle system for visualising sound. By using their AKAudioAnalyzer class to control the positions, spins and masses of gravity wells based on the iPad's microphone input, we've been able to get this demo together in next to no time:

Discover how the Force.com Web Services Connector (WSC) is a code-generation tool and runtime library for use with Force.com Web services, brought to you in partnership with Salesforce.

Topics:

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}