annotate CollidoscopeApp/src/ParticleController.cpp @ 4:ab6db404403a

commented JackDevice
author Fiore Martin <f.martin@qmul.ac.uk>
date Wed, 13 Jul 2016 12:31:37 +0200
parents 02467299402e
children 75b744078d66
rev   line source
f@0 1 #include "ParticleController.h"
f@0 2 #include "cinder/Rand.h"
f@0 3
f@0 4 #include <type_traits>
f@0 5
f@0 6 using namespace ci;
f@0 7 using std::list;
f@0 8
f@0 9 ParticleController::ParticleController() :
f@0 10 mNumParticles( 0 )
f@0 11
f@0 12 {
f@4 13 // uses Cinder (and OpenGL) virtual buffer object based drawing
f@4 14 // see ParticleSphereCPU example in Cinder library
f@4 15
f@0 16 mParticles.assign( kMaxParticles, Particle() );
f@0 17 mParticlePositions.assign( kMaxParticles, vec2( -1, -1 ) );
f@0 18
f@0 19 mParticleVbo = gl::Vbo::create( GL_ARRAY_BUFFER, mParticlePositions, GL_DYNAMIC_DRAW );
f@0 20
f@0 21 geom::BufferLayout particleLayout;
f@0 22 particleLayout.append( geom::Attrib::POSITION, 2, sizeof( vec2 ), 0 );
f@0 23
f@0 24 auto mesh = gl::VboMesh::create( mParticlePositions.size(), GL_POINTS, { { particleLayout, mParticleVbo } } );
f@0 25
f@4 26 // creates glsl program to run the batch with
f@0 27 #if ! defined( CINDER_GL_ES )
f@0 28 auto glsl = gl::GlslProg::create( gl::GlslProg::Format()
f@0 29 .vertex( CI_GLSL( 150,
f@0 30 uniform mat4 ciModelViewProjection;
f@0 31 in vec4 ciPosition;
f@0 32
f@0 33 void main( void ) {
f@0 34 gl_Position = ciModelViewProjection * ciPosition;
f@0 35 gl_PointSize = 1.0;
f@0 36 }
f@0 37 ) )
f@0 38 .fragment( CI_GLSL( 150,
f@0 39 out vec4 oColor;
f@0 40
f@0 41 void main( void ) {
f@0 42 oColor = vec4( 1.0f, 1.0f, 1.0f, 1.0f );
f@0 43 }
f@0 44 ) )
f@0 45 );
f@0 46
f@0 47 mParticleBatch = gl::Batch::create( mesh, glsl );
f@0 48
f@0 49 #else
f@0 50 auto glsl = gl::GlslProg::create( gl::GlslProg::Format()
f@0 51 .vertex( CI_GLSL( 100,
f@0 52 uniform mat4 ciModelViewProjection;
f@0 53 attribute vec4 ciPosition;
f@0 54
f@0 55 void main( void ) {
f@0 56 gl_Position = ciModelViewProjection * ciPosition;
f@0 57 gl_PointSize = 1.0;
f@0 58 }
f@0 59 ) )
f@0 60 .fragment( CI_GLSL( 100,
f@0 61 precision highp float;
f@0 62
f@0 63 void main( void ) {
f@0 64 gl_FragColor = vec4( 1, 1, 1, 1 );
f@0 65 }
f@0 66 ) )
f@0 67 );
f@0 68
f@0 69 mParticleBatch = gl::Batch::create( mesh, glsl );
f@0 70 #endif
f@0 71
f@0 72
f@0 73 }
f@0 74
f@0 75 void ParticleController::updateParticles()
f@0 76 {
f@4 77 // update the positions of the particles and dispose them if they're reached their timespan
f@0 78 for ( size_t i = 0; i < mNumParticles; i++ ){
f@0 79
f@0 80 Particle &particle = mParticles[i];
f@0 81 vec2 &pos = mParticlePositions[i];
f@0 82
f@0 83 particle.mAge++;
f@0 84
f@0 85
f@0 86 if ( (!particle.mFlyOver && particle.mAge > particle.mLifespan)
f@0 87 || (particle.mFlyOver && particle.mAge >= 300) ){
f@0 88 // dispose particle
f@0 89 mParticles[i] = mParticles[mNumParticles - 1];
f@0 90 mParticlePositions[i] = mParticlePositions[mNumParticles - 1];
f@0 91 mParticlePositions[mNumParticles - 1].x = -1.0f;
f@0 92 mParticlePositions[mNumParticles - 1].y = -1.0f;
f@0 93 mNumParticles--;
f@0 94 continue;
f@0 95 }
f@0 96
f@0 97 pos += particle.mVel;
f@0 98 if ( ci::distance( pos, particle.mCloudCenter ) > particle.mCloudSize && !particle.mFlyOver ){
f@0 99 particle.mVel = rotate<float>( particle.mVel, 5 );
f@0 100 }
f@0 101 }
f@0 102
f@4 103 // Copy particle data onto the GPU.
f@4 104 // Map the GPU memory and write over it.
f@0 105 void *gpuMem = mParticleVbo->mapReplace();
f@0 106 memcpy( gpuMem, mParticlePositions.data(), mParticlePositions.size() * sizeof( vec2 ) );
f@0 107 mParticleVbo->unmap();
f@0 108 }
f@0 109
f@0 110 void ParticleController::addParticles(int amount, const vec2 &initialLocation, const float cloudSize)
f@0 111 {
f@4 112 // reduce the particles liearly to the total number of particles already present
f@4 113 // the more particles aleary present the less particle are added
f@0 114 int reduction = ci::lmap<int>(mNumParticles, 0, kMaxParticles, 0, kMaxParticleAdd);
f@0 115 amount -= reduction;
f@0 116
f@0 117 if ( mNumParticles + amount > kMaxParticles ){
f@4 118 //a.k.a. return if reached kMaxParticles
f@0 119 amount = kMaxParticles - mNumParticles;
f@0 120 }
f@0 121
f@0 122 if( amount <= 0 )
f@0 123 return;
f@0 124
f@0 125 for( size_t i = 0; i < amount; i++ ){
f@0 126 // init new particle
f@0 127 Particle &particle = mParticles[mNumParticles + i];
f@0 128 vec2 &pos = mParticlePositions[mNumParticles + i];
f@0 129
f@0 130 pos = initialLocation + Rand::randVec2() * 5.0f; // find a location nearby the initial location
f@0 131 particle.mCloudCenter = pos;
f@0 132 particle.mVel = Rand::randVec2() * Rand::randFloat( 1.0f, 5.0f );
f@0 133 particle.mCloudSize = cloudSize;
f@0 134 particle.mAge = 0;
f@0 135 particle.mLifespan = Rand::randInt( 30, 60 );
f@0 136 particle.mFlyOver = (Rand::randInt( 500 ) == 0);
f@0 137
f@0 138 }
f@0 139
f@0 140 mNumParticles += amount ;
f@0 141
f@0 142 }
f@0 143
f@0 144
f@0 145