In this recipe, we will learn how to apply simple physics to object particles and generate sound upon the collision of two objects.
In this example, we are using code described in the recipe Generating a sine oscillator in this chapter, so please refer to that recipe.
We will create a Cinder application to illustrate the mechanism:
#include "cinder/audio/Output.h" #include "cinder/audio/Callback.h" #include "cinder/Rand.h" #include "cinder/CinderMath.h" #include "ParticleSystem.h"
main
class for particle simulation:ParticleSystem mParticleSystem; Vec2fattrPosition; float attrFactor; float attrRadius;
main
class to make the particles interactive:bool dragging; Particle *dragParticle;
void audioCallback( uint64_t inSampleOffset, uint32_t ioSampleCount,audio::Buffer32f *buffer ); float mSndFrequency; float mPhase, mPhaseAdd; vector<float> mOutput;
setup
method:mRunning= true; dragging = false; attrPosition = getWindowCenter(); attrRadius = 75.f; attrFactor = 0.02f; int numParticle= 10; for( int i=0; i<numParticle; i++ ){ float x = Rand::randFloat( 0.0f, getWindowWidth() ); float y = Rand::randFloat( 0.0f, getWindowHeight() ); float radius = Rand::randFloat(2.f, 40.f); Rand::randomize(); float mass = radius; float drag = 0.95f; Particle *particle = new Particle( Vec2f( x, y ), radius, mass, drag ); mParticleSystem.addParticle( particle ); }
setup
method:mSndFrequency = 0.0f; mPhase = 0.0f; mPhaseAdd = 0.0f; audio::Output::play( audio::createCallback( this, &MainApp::audioCallback ) );
resize
method to update the attractor position whenever an application window will be resized:void MainApp::resize(ResizeEvent event) { attrPosition = getWindowCenter(); }
void MainApp::mouseDown(MouseEvent event)
{ dragging = false; std::vector<Particle*>::iterator it; for( it = mParticleSystem.particles.begin(); it != mParticleSystem.particles.end(); ++it ) { if( (*it)->position.distance(event.getPos()) < (*it)->radius ) { dragging = true; dragParticle = (*it); } } } void MainApp::mouseUp(MouseEvent event) { dragging = false; }
update
method, add the following code for sound frequency calculation:float maxFrequency = 15000.0f; float targetFrequency = ( getMousePos().y / (float)getWindowHeight() ) * maxFrequency; targetFrequency = mSndFrequency - 10000.f; mSndFrequency = math<float>::clamp( targetFrequency, 0.0f, maxFrequency );
update
method, add the following code for particle movement calculation. At this point, we are detecting collisions and calculating the sound frequency:std::vector<Particle*>::iterator it; for( it = mParticleSystem.particles.begin(); it != mParticleSystem.particles.end(); ++it ) { std::vector<Particle*>::iterator it2; for( it2 = mParticleSystem.particles.begin(); it2 != mParticleSystem.particles.end(); ++it2 ) { float d = (*it)->position.distance( (*it2)->position ); float d2 = (*it)->radius + (*it2)->radius; if(d >0.f&& d <= d2 ) { (*it)->forces += -1.1f * ( (*it2)->position - (*it)->position ); (*it2)->forces += -1.1f * ( (*it)->position - (*it2)->position ); mSndFrequency = 2000.f; mSndFrequency+= 10000.f * (1.f - ((*it)->radius / 40.f)); mSndFrequency+= 10000.f * (1.f - ((*it2)->radius / 40.f)); } } Vec2f attrForce = attrPosition - (*it)->position; attrForce *= attrFactor; (*it)->forces += attrForce; } mSndFrequency = math<float>::clamp( mSndFrequency, 0.0f, maxFrequency );maxFrequency );
if(dragging) { dragParticle->forces = Vec2f::zero(); dragParticle->position = getMousePos(); } mParticleSystem.update();
draw
method as follows:gl::clear( Color::white() ); gl::setViewport(getWindowBounds()); gl::setMatricesWindow( getWindowWidth(), getWindowHeight() ); gl::color( Color::black() ); mParticleSystem.draw();
We are generating random particles with applied physics and collision detection. While collision is detected, a frequency of a sine wave is calculated based on the particles' radii.
Inside the update
method, we are iterating through the particles and checking the distance between each of them to detect collision, if it occurs. A generated frequency is calculated from the radii of the colliding particles—the bigger the radius, the lower the frequency of the sound.
3.144.40.189